How get content width of a QListView



  • Hi,

    I want to get the width of the content of a QListView. Indeed, this width is different if vertical scrollbar is visible or not. In my application, scrollbar of QListView is visible only if it is needed.

    So, I know I can get the width of the QListView, but this width include the scrollbar.

    So to know the width without the scrollbar, I have two solutions:

    • Find a solution to get the information of the scrollbar is visible or not (because I know how get the scrollbar witdh)
    • Find the size of the QListView that does not include the scrollbar.

    But I don't know how do any one of this methods... Can you help me please?

    Floréal.



  • Hi,

    I have not found how do that with QFontMetrics as I don't know how set wordwrap with it.

    Anyway, Y have succeeded to make something that works almost fine with QLabels. But it works only if I don't resize the window.

    See these screenshots:

    Normal size, when the program is launched:
    !http://www.hostingpicture.fr/upload/e5ff0755d35ce721ddcc3cc03c7be5bb.png(Avant)!

    When I enlarge the window, I see that:
    !http://www.hostingpicture.fr/upload/fcb1add302955f12e8cfa1b4213874ea.png(Après)!

    So, the items are resized BUT the following item was placed always at the same place as if the size of items are always the same.

    How correct that?

    To help you, I post my code :

    MainWindow.h:
    @#ifndef MAINWINDOW_H
    #define MAINWINDOW_H

    #include <QMainWindow>
    #include <QStandardItemModel>
    #include <QListView>
    #include <QStandardItem>

    namespace Ui {
    class MainWindow;
    }

    class MainWindow : public QMainWindow
    {
    Q_OBJECT

    public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

    private:
    Ui::MainWindow *ui;

    private:
    QStandardItemModel *model1;

    public slots:
    void init();
    };

    #endif // MAINWINDOW_H@

    MainWindow.cpp:
    @#include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include "listviewdelegate.h"

    MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
    {
    ui->setupUi(this);
    }

    MainWindow::~MainWindow()
    {
    delete ui;
    }

    void MainWindow::init()
    {
    model1 = new QStandardItemModel(this);
    ui->listView->setIconSize(QSize(15,15));
    ui->listView->setModel(model1);
    ui->listView->setItemDelegate(new ListViewDelegate(0));
    for (int var = 0; var < 5; ++var) {
    QStandardItem* item = new QStandardItem("1.2.0|Bonjour le monde Bonjour le monde Bonjour le monde Bonjour le monde Bonjour le monde Bonjour le monde Bonjour le monde Bonjour le monde Bonjour le monde Bonjour le monde le monde Bonjour le monde le monde ");
    model1->appendRow(item);
    }
    show();
    }@

    listviewdelegate.h:
    @#ifndef LISTVIEWDELEGATE_H
    #define LISTVIEWDELEGATE_H

    #include <QApplication>
    #include <QFlags>
    #include <QLabel>
    #include <QPainter>
    #include <QStyledItemDelegate>
    #include <QTextDocument>

    class ListViewDelegate : public QStyledItemDelegate
    {
    public:
    ListViewDelegate(int wiLu);

    protected:
    void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const;
    QSize sizeHint(const QStyleOptionViewItem & option, const QModelIndex & index ) const;
    int wi;
    };

    #endif // LISTEVIEWDELEGATE_H
    @

    @#include "listviewdelegate.h"
    #include <QScrollBar>
    #include <QStringList>
    #include <QFontMetrics>

    ListViewDelegate::ListViewDelegate(int wiLu)
    {
    wi = wiLu;
    }

    void ListViewDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
    {
    QStyleOptionViewItemV4 opt = option;
    initStyleOption(&opt, index);

    QString allLine = opt.text;
    QStringList parts = allLine.split("|");
    QString indexItem = parts[0];
    QString line = parts[1];
    QSize s = opt.widget->baseSize();
    
    // draw correct background
    opt.text = "";
    QStyle *style = opt.widget ? opt.widget->style() : QApplication::style();
    style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, opt.widget);
    
    QTextDocument doc;
    doc.setHtml(opt.text);
    doc.setTextWidth(s.width());
    
    //QRect rect = opt.rect;
    QRect rect (opt.rect.left(), opt.rect.top(), opt.rect.width(),opt.rect.height());
    QPalette::ColorGroup cg = opt.state & QStyle::State_Enabled ? QPalette::Normal : QPalette::Disabled;
    if (cg == QPalette::Normal && !(opt.state & QStyle::State_Active))
        cg = QPalette::Inactive;
    
    // set pen color
    if (opt.state & QStyle::State_Selected)
        painter->setPen(opt.palette.color(cg, QPalette::HighlightedText));
    else
        painter->setPen(opt.palette.color(cg, QPalette::Text));
    
    // draw puce
    int level = 0;
    if (indexItem.contains(".")) {
        QStringList nums = indexItem.split('.');
        QString puce = nums[nums.length() - 2];
        level = nums.length() - 2;
        painter->drawText(rect.left() + 2 + level * 30, rect.top(), 18, 20, 0, puce+'.');
    }
    else {
        level = indexItem.toInt();
        painter->fillRect(rect.left() + 2 + level * 30, rect.top() + 2, 8, 8, Qt::black);
    }
    
    // draw text
    painter->drawText(QRect(rect.left() + 24 + (level * 30), rect.top(), rect.width() - 28 - (level * 30), rect.height()),
                      Qt::AlignJustify | Qt::AlignVCenter | Qt::TextWordWrap, line);
    

    }
    QSize ListViewDelegate::sizeHint(const QStyleOptionViewItem & option, const QModelIndex & index ) const
    {
    QStyleOptionViewItemV4 opt = option;
    initStyleOption(&opt, index);

    QString allLine = opt.text;
    QStringList parts = allLine.split("|");
    QString line = parts[1];
    QString indexItem = parts[0];
    
    int level = 0;
    if (indexItem.contains(".")) {
    
    }
    else {
        level = indexItem.toInt();
    }
    
    QLabel* text = new QLabel();
    text->setWordWrap(true);
    
    int sizeScroll = QApplication::style()->pixelMetric(QStyle::PM_ScrollBarExtent);
    text->setMaximumWidth(opt.widget->width() - 28 - (level * 30) - 8 - sizeScroll);
    text->setMinimumWidth(opt.widget->width() - 28 - (level * 30) - 8 - sizeScroll);
    text->setText(line);
    text->adjustSize();
    return QSize(opt.widget->width() - 8 - sizeScroll, text->size().height());
    

    }
    @

    So, may be we have to define some repaint while window is resized, I don't know...

    Please help me,

    Thank you for your help, and in advance for your future help,

    Floréal.


  • Lifetime Qt Champion



  • Thank you for your help.

    Now I use QFontMetrics well, but the problem is still the same. I have a little bit simplified the code so maybe you will better understand where is the problem.

    When I launch the application, the list is shown very well:
    !http://www.hostingpicture.fr/upload/c8f1b2b307e9d2d2f5a563c76aa89991.png(Before)!

    But if I enlarge the window, increasing width, The list is bad:
    !http://www.hostingpicture.fr/upload/b23c2faed70cf29ac18c52eab347f631.png(After)!

    So if I understand the problem it was like it:

    • Height is effectively changed and adapted to the text
    • But y value where each item of the list is painted is never changed

    So, now, I need to find a solution to make the y value of each item when window is resized refreshed.

    Below is my new code for listviewdelegate.cpp :
    @#include "listviewdelegate.h"
    #include <QScrollBar>
    #include <QStringList>
    #include <QFontMetrics>

    ListViewDelegate::ListViewDelegate(int wiLu)
    {
    wi = wiLu;
    }

    void ListViewDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
    {
    QStyleOptionViewItemV4 opt = option;
    initStyleOption(&opt, index);

    QString allLine = opt.text;
    QStringList parts = allLine.split("|");
    QString indexItem = parts[0];
    QString line = parts[1];
    QSize s = opt.widget->baseSize();
    
    // draw correct background
    opt.text = "";
    QStyle *style = opt.widget ? opt.widget->style() : QApplication::style();
    style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, opt.widget);
    
    QTextDocument doc;
    doc.setHtml(opt.text);
    doc.setTextWidth(s.width());
    
    //QRect rect = opt.rect;
    QRect rect (opt.rect.left(), opt.rect.top(), opt.rect.width(),opt.rect.height());
    QPalette::ColorGroup cg = opt.state & QStyle::State_Enabled ? QPalette::Normal : QPalette::Disabled;
    if (cg == QPalette::Normal && !(opt.state & QStyle::State_Active))
        cg = QPalette::Inactive;
    
    // set pen color
    if (opt.state & QStyle::State_Selected)
        painter->setPen(opt.palette.color(cg, QPalette::HighlightedText));
    else
        painter->setPen(opt.palette.color(cg, QPalette::Text));
    
    // draw text
    painter->drawText(QRect(rect.left() + 24, rect.top(), rect.width() - 28, rect.height()),
                      Qt::AlignJustify | Qt::AlignVCenter | Qt::TextWordWrap, line);
    

    }
    QSize ListViewDelegate::sizeHint(const QStyleOptionViewItem & option, const QModelIndex & index ) const
    {
    QStyleOptionViewItemV4 opt = option;
    initStyleOption(&opt, index);

    QString allLine = opt.text;
    QStringList parts = allLine.split("|");
    QString line = parts[1];
    QString indexItem = parts[0];
    
    int sizeScroll = QApplication::style()->pixelMetric(QStyle::PM_ScrollBarExtent);
    
    QFont font;
    
    QFontMetrics text (font);
    QRect rect = text.boundingRect(0, 0, opt.widget->width() - 8 - sizeScroll, 0, Qt::TextWordWrap, line);
    
    return QSize(rect.width(), rect.height());
    

    }
    @

    The other files where not modified, you can find the code in my previous post.

    Thank you for your help, and in advance for your future help :)

    Floréal.



  • Up please... There is no solution to solve my problem?


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.