15.1.216. tablet_qt/lib/sizehelpers.h

/*
    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/>.
*/

/*
    OPTIONAL LGPL: Alternatively, this file may be used under the terms of the
    GNU Lesser General Public License version 3 as published by the Free
    Software Foundation. You should have received a copy of the GNU Lesser
    General Public License along with CamCOPS. If not, see
    <https://www.gnu.org/licenses/>.
*/

#pragma once

#include <QSizePolicy>
#include <QStyle>
class QFrame;
class QLayout;
class QLabel;
class QPushButton;
class QStyleOptionButton;
class QStyleOptionFrame;
class QWidget;


namespace sizehelpers {

// Size policies that take a few statements to create (i.e. that have
// height-for-width set!).
// Remember: these take the widget's sizeHint() as the reference.

/*

QSizePolicy: https://doc.qt.io/qt-6.5/qsizepolicy.html

    QSizePolicy::GrowFlag	1	The widget can grow beyond its size hint if necessary.
    QSizePolicy::ExpandFlag	2	The widget should get as much space as possible.
    QSizePolicy::ShrinkFlag	4	The widget can shrink below its size hint if necessary.
    QSizePolicy::IgnoreFlag	8	The widget's size hint is ignored. The widget will get as much space as possible.

So...

Fixed = 0

    "Be exactly size X."

Minimum = GrowFlag

    "Be at least X. I don't need more, but you can give me more."

Maximum = ShrinkFlag

    "Be at most X. You can shrink me if you want."

Preferred = GrowFlag | ShrinkFlag

    "I'd like to be X. You can shrink me if you want. You can enlarge me if
    you want, but I don't need more."

MinimumExpanding = GrowFlag | ExpandFlag

    "Be at least X, but I'd like to be as large as possible."

Expanding = GrowFlag | ShrinkFlag | ExpandFlag

    "X is a reasonable size. You can enlarge or shrink me if you want, but
    I'd like to be as large as possible."

Ignored = ShrinkFlag | GrowFlag | IgnoreFlag

    "Be as large as possible!"

When the "height-for-width" flag is set, meaning "my height depends on my
width", these get more complicated -- see below.

The names of all the functions below have the horizontal policy then the
vertical policy.

*/


// "X is a reasonable horizontal size, but expand me far as possible
// horizontally (and you can shrink me below X if required). Once my vertical
// height Y has been determined from my actual width, it is fixed."
QSizePolicy expandingFixedHFWPolicy();

// "X is a reasonable horizontal size, but expand me far as possible
// horizontally (and you can shrink me below X if required). Once my vertical
// height Y has been determined from my actual width, it is preferred; you
// can enlarge me or shrink me vertically if you want, but I don't need more
// than Y vertically."
QSizePolicy expandingPreferredHFWPolicy();

// "X is a reasonable horizontal size, but expand me far as possible
// horizontally (and you can shrink me below X if required). Once my vertical
// height Y has been determined from my actual width, it is my vertical
// maximum, though you can shrink me vertically if you want."
QSizePolicy expandingMaximumHFWPolicy();

// "X is a reasonable horizontal size, but expand me far as possible
// horizontally (and you can shrink me below X if required). Once my vertical
// height Y has been determined from my actual width, that is a reasonable
// size; you can expand or shrink me vertically, but I would like to be as
// large as possible vertically as well."
QSizePolicy expandingExpandingHFWPolicy();

// "X is my maximum horizontal size; you can shrink me horizontally if you
// want. Once my vertical height Y has been determined from my actual width,
// then it is fixed."
QSizePolicy maximumFixedHFWPolicy();

// "X is my maximum horizontal size; you can shrink me horizontally if you
// want. Once my vertical height Y has been determined from my actual width,
// then it is my vertical maximum; you can shrink me vertically if you want."
QSizePolicy maximumMaximumHFWPolicy();

// "X is my preferred horizontal size; you can shrink me horizontally if you
// want, or expand me, but I don't want more. Once my vertical height Y has
// been determined from my actual width, then it is my preferred height, but
// you can shrink or expand me vertically if you want (but I don't need more)."
QSizePolicy preferredPreferredHFWPolicy();

// "X is my preferred horizontal size; you can shrink me horizontally if you
// want, or expand me, but I don't want more. Once my vertical height Y has
// been determined from my actual width, then it is fixed."
QSizePolicy preferredFixedHFWPolicy();

// The ugly stuff you have to do for widgets that own height-for-width
// widgets if you use Qt layouts like QVBoxLayout.
// This is NOT used within our better HFW framework; see gui_defines.h.
void resizeEventForHFWParentWidget(QWidget* widget);

// More size helper functions, e.g. "how much extra space do I need for
// the stylesheet margins?"
QSize contentsMarginsAsSize(const QWidget* widget);
QSize contentsMarginsAsSize(const QLayout* layout);

// Returns a layout's spacing() as a QSize(2 * spacing(), 2 * spacing()) --
// that is, when you add all the spacing up.
QSize spacingAsSize(const QLayout* layout);

// How much extra space does a QWidget need for its layout margins or its
// stylesheet?
// - widget: the widget to examine
// - opt: "option" parameter passed to QStyle::sizeFromContents()
// - child_size: "contentsSize" parameter passed to QStyle::sizeFromContents()
// - add_style_element: add the size for the style, as well as for the margins
//   of any layout installed on the widget?
// - contents_type: "type" parameter passed to QStyle::sizeFromContents()
QSize widgetExtraSizeForCssOrLayout(const QWidget* widget,
                                    const QStyleOption* opt,
                                    const QSize& child_size,
                                    bool add_style_element,
                                    QStyle::ContentsType contents_type);

// Guess the QStyle::ContentsType applicable to a widget.
// I don't know why this should be necessary...
QStyle::ContentsType guessStyleContentsType(const QWidget* widget);

// Autodetecting version.
QSize widgetExtraSizeForCssOrLayout(const QWidget* widget);

// widgetExtraSizeForCssOrLayout() for QPushButton.
QSize pushButtonExtraSizeRequired(const QPushButton* button,
                                  const QStyleOptionButton* opt,
                                  const QSize& child_size);

// widgetExtraSizeForCssOrLayout() for QFrame.
QSize frameExtraSizeRequired(const QFrame* frame,
                             const QStyleOptionFrame* opt,
                             const QSize& child_size);

// widgetExtraSizeForCssOrLayout() for QLabel.
QSize labelExtraSizeRequired(const QLabel* label,
                             const QStyleOptionFrame* opt,
                             const QSize& child_size);

// Does the widget have a fixed height that is equal to "height"?
bool fixedHeightEquals(QWidget* widget, int height);

// Is a size policy an HFW one that allows vertical shrinkage?
bool canHFWPolicyShrinkVertically(const QSizePolicy& sp);

// Is this an HFW widget that appears to have an area constraint, and trading
// width for height -- e.g. word-wrapped text -- detected as one whose
// preferred height appears (in a very simple test) to get SMALLER as its
// width gets larger?
bool isWidgetHFWTradingDimensions(const QWidget* widget);

// Is this an HFW widget that appears to have an aspect ratio constraint, e.g.
// a resizable widget -- detected as one whose preferred height appears (in a
// very simple test) to get LARGER as its width gets larger?
bool isWidgetHFWMaintainingAspectRatio(const QWidget* widget);


}  // namespace sizehelpers