-1

I have created an expandable ListView which extends from the QListView, everything works well when I just want to show the Header data (Item which is not expanded) because I gave it a hard-coded height which is 64, the details appear when expanding the item. But the problem is I do not know the exact height of the details because the details can one line or more, I want to fit the Item height according to the item content.

Here the code which is handling click listener when the item expanding or collapsing:

LogListItemDelegate *delegate = static_cast<LogListItemDelegate *>(itemDelegate());
QStandardItem *item = static_cast<QStandardItemModel *>(model())->itemFromIndex(index);
bool expand = delegate->isExpandable() && mapFromGlobal(QCursor::pos()).x() >= visualRect(index).width() - 48;
bool expanded = index.data(LogListItemDelegate::DT_Expanded).toBool();

// here the height returned is header height, no containing the details which it is in expanding mode
int height = item->sizeHint().height();

        if (!expanded) {
            item->setData(true, LogListItemDelegate::DT_Expanded);
            item->setSizeHint(QSize(0, 150)); // 150 here must be dynamically calculated
        } else {
            item->setData(false, LogListItemDelegate::DT_Expanded);
            item->setSizeHint(QSize(0, 64)); // 64 is the header height, no prolem
        }

Now the question is: How to calculate the height when item expanded?

Result:

enter image description here

Edit:

It is when I want to add the message to the list
void LogListView::addMessage(const QJsonObject &msg, const bool append)
{
    static int id = 1; // unique id for log items
    auto *item = new QStandardItem();
    item->setEditable(false);
    item->setData(QString("%1").arg(id++, 5, 10, QChar('0')), LogListItemDelegate::DT_Id);
    item->setData(msg["icon"], LogListItemDelegate::DT_ICON);
    item->setData(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss"), LogListItemDelegate::DT_Timestamp);
    item->setData(msg["title"], LogListItemDelegate::DT_Title);
    item->setData(msg["subtitle"], LogListItemDelegate::DT_Subtitle);
    item->setData(msg["details"], LogListItemDelegate::DT_Details);
    item->setData(false, LogListItemDelegate::DT_Expanded);
    // here I am unable to calculate the height, because the details does not have a specific height to set here, 
    // so when append the item to the list it is unvisible. If set the height 64, it is the exact height of the item without details, which is good
    //item->setSizeHint(QSize(0, 64));

    static_cast<QStandardItemModel *>(model())->appendRow(item);
    scrollToBottom();
}

It is the code in sizeHint()

QSize LogListItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    bool expanded = index.data(DT_Expanded).toBool();
    QFont fntDetials = option.font;
    fntDetials.setPointSize(12);
    QRect r = option.rect;
    QFontMetrics fm(fntDetials);
    QString details = index.data(DT_Details).toString();
    QRect br = fm.boundingRect(r, Qt::TextWordWrap, details);
    return QSize(option.rect.width(), br.height()+64);
}

Unfortunately not working..., I think Qt can look the Android ListView and its recycle functionality to solve the ListView problem, in this way, I think it is very very painful.

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
Bahramdun Adil
  • 5,907
  • 7
  • 35
  • 68
  • 1
    QStandardItem is not a visual element but an element that keeps data. The geometrical task depends on the delegate that has the sizeHint method, so the problem is in the delegate. To give you a solution, it shows the code of the delegate – eyllanesc Nov 20 '18 at 16:38
  • @eyllanesc First of all thanks for the replying! I did not find anything in Delegate which passes the correct height and width to the ListView. Can you show me how I can pas the height of the details to the ListView, I can calculate the height of the details, but there is no way to the set the height to retrieve it back in the when item clicked? – Bahramdun Adil Nov 20 '18 at 16:43
  • @BahramdunAdil, I thought you don't like the solution. [The answer](https://stackoverflow.com/a/53110350/5366641) stays unaccepted, yet you are using my code. This does not seem like a fair play. _I have created an expandable ListView_ sounds like the holy truth. – scopchanov Nov 21 '18 at 01:55
  • @scopchanov The problem still remains unsolved, so when the function completely implemented, then I will come back, thanks and accept the answers which were really solved the problem. By the way, your answer has been got the vote up. And also your solution was not expandable item view. And also I did not use your code even one line. Because your solution is not something I want. Thanks!! – Bahramdun Adil Nov 21 '18 at 02:30
  • @BahramdunAdil, which problem remains unsolved? You aksed a question and got an answer with a __working example__. Then you have complained that it is too complicated for you. Though, you used my solution and did not even mention (in your current question) where did you get it from. With such an attiude you won't get too much help around. But the best part is, that I know how to make the height of the expanded item fit the text, because I have written the code, and you don't. – scopchanov Nov 21 '18 at 02:42
  • @scopchanov Beside to vote up, I have also accepted your answer, now you can go for a relax. By the way, thank you for your all effort! – Bahramdun Adil Nov 21 '18 at 02:59
  • Hi, Do you have source code? Or git address? I have an idea on it. Thanks. Bahramdun Adil – VOLVO May 14 '22 at 20:04

1 Answers1

2

If you want to set a custom size you should use the sizeHint method of QStyledItemDelegate, for example:

#include <QApplication>
#include <QStyledItemDelegate>
#include <QListView>
#include <QStandardItemModel>

class HeightDelegate: public QStyledItemDelegate
{
public:
    using QStyledItemDelegate::QStyledItemDelegate;
    QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override{
        QSize s = QStyledItemDelegate::sizeHint(option, index);
        // some calculation
        int h = (index.row()+1)*20;
        s.setHeight(h);
        return s;
    }
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QListView w;
    QStandardItemModel model;
    HeightDelegate delegate;
    w.setItemDelegate(&delegate);
    w.setModel(&model);
    for(int i=0; i<8; i++){
        QStandardItem *it = new QStandardItem(QString::number(i));
        it->setBackground(QBrush(QColor(qrand()%255, qrand()%255, qrand()%255)));
        model.appendRow(it);
    }
    w.show();
    return a.exec();
}

enter image description here

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
  • Thanks for the reply, I have tried your solution, but the problem not solved completely. Now the in the sizeHint() when I gave right height, and after when I change the width (to small size) of the window, then I lose the expand icon, then when I change it to bigger width, and after to smaller, I also lose the Icons. – Bahramdun Adil Nov 21 '18 at 02:36
  • @BahramdunAdil if you realize your problem depends on your implementation, and I can only help you when you provide a [mcve]. – eyllanesc Nov 21 '18 at 02:38
  • Thanks! @eeyllanesc! OK, I will try to post the code, because the code is so long, not very fair to post here which makes the question to read. – Bahramdun Adil Nov 21 '18 at 02:46
  • @eyllanesc, it is unfortunatelly a waste of time. The OP won't appreciate your effort. – scopchanov Nov 21 '18 at 02:46
  • 1
    @BahramdunAdil A [mcve] does not refer to the code of your project but if your code is extensive then you create another project focused on the functionality, for example my code is a possible start, my code only focuses on the functionality. – eyllanesc Nov 21 '18 at 02:49
  • 1
    @scopchanov That is the decision of the OP, I will not judge your action because here the OP is not judged (unless it violates the rules), besides the answer is not only for the OP, it is for the community :-) – eyllanesc Nov 21 '18 at 02:51
  • @eyllanesc Thank you brother very much, you are the best. – Bahramdun Adil Nov 21 '18 at 02:52
  • 1
    @BahramdunAdil I recommend you strive and provide an early [mcve], remember that a good question is as valuable as a good answer. – eyllanesc Nov 21 '18 at 02:53
  • @eyllanesc Hi sir! I have tried many ways to implement the Qt ListView, but unfortunately, it was not working, I was unable to calculate the needed height for the item, I have edited the question, you can have a look to it. Thanks in advance!! – Bahramdun Adil Nov 29 '18 at 15:06