Hello together I'm experimenting with qt and have some questions about this whole
Model-Delegate-Proxy stuff.
What I want to achieve is to show a list of Persons in a QListView, with the ability of
filtering, and showing letter-captions, (Like many List-Controls on mobileOS) and writing the whole information for a person in 1 cell.
-----------------------
|A |
-----------------------
|Abigail Familly-Name |
|Audrey Familly-Name |
-----------------------
|C |
-----------------------
|Christian Familly-Name|
-----------------------
|D |
-----------------------
|Daniel Familly-Name |
-----------------------
I have a Class: Person where I have the structure of the information (Name,Famillyname,day of b.... aso.)
On the MODEL side I have a QAbstractListModel
..........
explicit PersonModel
(QObject *parent
= 0);
QVariant headerData
(int section, Qt
::Orientation orientation,
int role
= Qt
::DisplayRole) const;
void FillData();
private:
Q_DISABLE_COPY(PersonModel);
QList<Person*> Persons;
...............
..........
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;
...............
To copy to clipboard, switch view to plain text mode
My data() function looks like this:
{
if (role == Qt::DisplayRole)
{
qRegisterMetaType<Person>("Person");
v.setValue<CPerson>(*Persons.at(index.row()));
return v;
}
}
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();
}
To copy to clipboard, switch view to plain text mode
Since I want to write different parts of the person class in on cell I return the
whole structure in a QVariant.
On the DELEGATE side my paint looks like this:
{
if (index.column() == 0) {
Person entry =index.model()->data(index).value<Person>();
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());
}
}
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());
}
}
To copy to clipboard, switch view to plain text mode
Here I'm placing Name and Surename.
On the proxy side I have QSortFilterProxyModel.
{
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,
{
QModelIndex index0
= sourceModel
()->index
(sourceRow,
0, sourceParent
);
Person data = sourceModel()->data(index0).value<Person>();
return (strData.contains(filterRegExp()));
}
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()));
}
To copy to clipboard, switch view to plain text mode
This stuff works so far.
Now I have 2 problems.
1. If I set the proxy filter e.g. on 'Da' the proxy is also filtering-out the Letter-Caption 'D', so that the List looks like
-----------------------
|Daniel Familly-Name |
-----------------------
What I have tried is to add a additional flag in my person class (Letter Caption yes/ no) and than to check this flag in filterAcceptsRow(). But than the list looks like this
-----------------------
|A |
-----------------------
-----------------------
|C |
-----------------------
-----------------------
|D |
-----------------------
|Daniel Familly-Name |
-----------------------
The letter-captions should only be drawn when there is a name.
My 2. problem is:
How can I convince Paint() and sizeHint() to draw this letter-captions in a
different way. (height of cell,BG-Color)?
Anyhow, I think that UserRoles could be the solution for my problems,
but my experiments with UserRoles were not really successful.
Have you any ideas how I could implement something like this, or is there
a better way of doing this, than the way I tried?
Thanks!
Bookmarks