Model/Delegate/Proxy

Alles rund um die Programmierung mit Qt
Antworten
skyline2000
Beiträge: 2
Registriert: 8. November 2008 01:00

Model/Delegate/Proxy

Beitrag von skyline2000 »

Hallo zusammen,

ich experimentiere gerade mit QT rum und habe eine Frage zu dem ganzen Model-Delegate-Proxy geflecht.

Eigentlich will ich eine Listenansicht(QListView) von eine List von Personen die ich durch das Verwenden vom Proxymodel auch noch filtern kann.
Dabei sollen die einzelnen Daten der jeweiligen Person immer in EINE Zelle geschrieben werden. Und abhängig davon welche Anfangsbuchstaben
in den zu anzeigenden Daten vorhanden sind soll es zur Eingliederung jeweils eine Zelle, die sich optisch vom rest unterscheidet, mit diesem
Buchstaben geben.

PERSON
-----------------------
A
-----------------------
Anton Nachname
Achim Nachname
-----------------------
C
-----------------------
Christian Nachname
-----------------------
D
-----------------------
Daniel Nachname

usw.

Für die Anzuzeigenden Personen habe ich eine Personen-Klasse "PERSON"
Diese beinhaltet die komplette Struktur der Person (Name,Nachname usw.)
Auf der Model Seite habe ich ein QAbstractListModel

Code: Alles auswählen

    
..........
explicit PersonModel(QObject *parent = 0);

    int columnCount(const QModelIndex &parent) const;
    int rowCount( const QModelIndex &index = QModelIndex()) const;

    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
    QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
    void FillData();

private:
    Q_DISABLE_COPY(PersonModel);
    QList<Person*> Persons;
...............
FillData() füllt einfach meine QList aus.
1.Frage hier, kann ich dass so machen oder ist es eleganter,eine
Insert Funktion ins Model zu implementieren und diese dann von
außen aufzurufen/zu füllen?

Meine data() Funktion sieht foglendermaßen aus

Code: Alles auswählen

QVariant PersonModel::data(const QModelIndex &index, int role) const
{
    if (role == Qt::DisplayRole)
    {
        qRegisterMetaType<Person>("Person");
        QVariant v;
        v.setValue<CPerson>(*Persons.at(index.row()));
        return v;
    }
    return QVariant();
}
da ich verschiedene Informationen aus der "Person" Klasse
in eine Zelle schreiben will gebe ich hier die komplette Struktur
als QVariant zurück.

Auf der Delegate-Seite habe ich ein QAbstractItemDelegate
Dort sieht meine Paint Funtion folgendermaßen aus

Code: Alles auswählen

void PersonDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    if (index.column() == 0) {
         Person entry =index.model()->data(index).value<Person>();
         painter->setFont( QFont("Arial",14,QFont::Bold));
         QRect NameRect = option.rect;
         NameRect.setLeft(5);
         painter->drawText(NameRect,Qt::AlignLeft,entry.GetName());
         NameRect.setLeft(0);
         NameRect.setRight(NameRect.width()-5);
         painter->setFont( QFont("Arial",14,QFont::Cursive));
         painter->drawText(NameRect,Qt::AlignRight,entry.GetSurename());
    }
}
Hier positioniere,zeichne ich einfach bestimmte Daten die mir data() als QVariant zurück gibt in der Zelle.

Zum schluss habe ich noch das QSortFilterProxyModel
mit den Funktionen lessThan(....) und filterAcceptsRow(....)

Code: Alles auswählen

bool MySortFilterProxyModel::lessThan(const QModelIndex &left,const QModelIndex &right) const
{
     Person leftData = sourceModel()->data(left).value<Person>();
     Person rightData = sourceModel()->data(right).value<Person>();

     QString leftString = leftData.GetName();
     QString rightString = rightData.GetName();

     return QString::localeAwareCompare(leftString, rightString) < 0;
 }

bool MySortFilterProxyModel::filterAcceptsRow(int sourceRow,
                             const QModelIndex &sourceParent) const
{
     QModelIndex index0 = sourceModel()->index(sourceRow, 0, sourceParent);
     Person data = sourceModel()->data(index0).value<Person>();
     QString strData = data.GetName();
     return (strData.contains(filterRegExp()));
}
Sowohl das Sortieren und das Herausfiltern funktioniert eigentlich soweit
gut.

Allerdings habe ich jetzt folgende Probleme. Setzte ich jetzt mein Proxy
Filter auf "Ch" bekomme ich eine Liste ohne eine "C" Einteilung.
-----------------------
Christian Nachname
-----------------------
Was ich machen kann ist das ich in der"PERSON" Klasse einfach mitführe
ob es sich um eine Einteilung handelt oder nicht und dann in der
filterAcceptsRow() einfach auswerte. Dann sieht die Ausgabe allerding
,bei oben genannter Filtereinstellung so aus:

PERSON
-----------------------
A
-----------------------
-----------------------
C
-----------------------
Christian Nachname
-----------------------
D

Ein zweites Problem ist unterschiedliche Darstellung dieser "Einteilungen".
Wie überzeuge ich die Paint() und sizeHint() im Delegate davon diese
anders darzustellen? Erneut über ein in "PERSON" mitgeschleiftes Flag?

Irgendwie werde ich das Gefühl nicht los das sich das Ganze mit UserRoles
einfacher abbilden lässt. Allerding bin ich damit nicht wirklich weit gekommen.

Falls Ihr eine Idee habt wie man das ganze eleganter/beseer lösen kann nur her damit.
upsala
Beiträge: 3946
Registriert: 5. Februar 2006 20:52
Wohnort: Landshut
Kontaktdaten:

Beitrag von upsala »

Bau dir halt einfach ein Delegate, daß die Überschrift mitzeichnet, wenn in der vorherigen Zeile ein anderer Buchstabe ist.
Antworten