15.1.1026. tablet_qt/widgets/heightforwidthlistwidget.cpp

/*
    Copyright (C) 2012, University of Cambridge, Department of Psychiatry.
    Created by Rudolf Cardinal (rnc1001@cam.ac.uk).

    This file is part of CamCOPS.

    CamCOPS is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    CamCOPS is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with CamCOPS. If not, see <https://www.gnu.org/licenses/>.
*/

// #define DEBUG_LAYOUT

#include "heightforwidthlistwidget.h"

#include <QDebug>
#include <QEvent>
#ifdef DEBUG_LAYOUT
    #include "lib/layoutdumper.h"
#endif


HeightForWidthListWidget::HeightForWidthListWidget(QWidget* parent) :
    QListWidget(parent)
{
    setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    // ... disable horizontal scroll bar (on small screens, we will word-wrap)
    setResizeMode(QListView::Adjust);
}

bool HeightForWidthListWidget::event(QEvent* e)
{
    switch (e->type()) {
        case QEvent::Resize:
            // ... Alternative is resizeEvent() but we need to trap other
            // events too
        case QEvent::LayoutRequest:
            // See QWidget::updateGeometry() -- they will come here
            {
                // At this point, we have already been resized, so can use
                // width();
                // https://doc.qt.io/qt-6.5/qwidget.html#resizeEvent
                const int n_items = count();
                for (int row = 0; row < n_items; ++row) {
                    QListWidgetItem* lwi = item(row);
                    if (!lwi) {
                        qWarning() << Q_FUNC_INFO << "null item()";
                        continue;
                    }
                    QWidget* widget = itemWidget(lwi);
                    if (!widget) {
                        qWarning() << Q_FUNC_INFO << "null itemWidget()";
                        continue;
                    }
                    const QSize size_hint = widgetSizeHint(widget);
                    lwi->setSizeHint(size_hint);
#ifdef DEBUG_LAYOUT
                    qDebug()
                        << Q_FUNC_INFO << "resizing list widget to" << size()
                        << "; setting QListWidgetItem sizeHint for widget"
                        << LayoutDumper::getWidgetDescriptor(widget) << "to"
                        << size_hint;
#endif
                }
            }
            break;
        default:
            break;
    }
    return QListWidget::event(e);
}

QSize HeightForWidthListWidget::widgetSizeHint(QWidget* widget) const
{
    if (!widget) {
        return QSize();
    }
    if (!widget->hasHeightForWidth()) {
        return widget->sizeHint();
    }
    const QRect list_contents_rect = contentsRect();
    const int list_width = list_contents_rect.width();
    const QSize widget_size_hint = widget->sizeHint();
    // Default implementation, QWidget::sizeHint, returns
    // its layout's totalSizeHint(), or an invalid size.

    const int widget_preferred_width = widget_size_hint.width();
    const int widget_new_width = qMin(widget_preferred_width, list_width);
    const int widget_new_height = widget->heightForWidth(widget_new_width);
    QSize result(widget_new_width, widget_new_height);
#ifdef DEBUG_LAYOUT
    qDebug() << Q_FUNC_INFO << "widget"
             << LayoutDumper::getWidgetDescriptor(widget) << "widget_size_hint"
             << widget_size_hint << "result" << result;
#endif
    return result;
}

// This was not perfect; menu item heights swap between e.g. 66 and 70
// pixels as you create the top menu and refresh the list (e.g. by clicking
// the lock button)... fixed by catching QEvent::LayoutRequest as well as
// QEvent::Resize.