Brooklyn/LibLXQT/configdialog/lxqtpageselectwidget.cpp
2021-11-03 11:36:41 +05:00

194 lines
6.4 KiB
C++

/* BEGIN_COMMON_COPYRIGHT_HEADER
* (c)LGPL2+
*
* LXQt - a lightweight, Qt based, desktop toolset
* https://lxqt.org
*
* Copyright: 2010-2011 Razor team
* Authors:
* Alexander Sokoloff <sokoloff.a@gmail.com>
*
* This program or library is free software; you can redistribute it
* and/or modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA
*
* END_COMMON_COPYRIGHT_HEADER */
#include "lxqtpageselectwidget.h"
#include <QDebug>
#include <QStyledItemDelegate>
#include <QEvent>
#include <QScrollBar>
#include <QApplication>
using namespace LXQt;
class PageSelectWidgetItemDelegate: public QStyledItemDelegate
{
public:
explicit PageSelectWidgetItemDelegate(PageSelectWidget *parent = nullptr);
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override;
private:
PageSelectWidget* mView;
};
/************************************************
************************************************/
PageSelectWidgetItemDelegate::PageSelectWidgetItemDelegate(PageSelectWidget *parent):
QStyledItemDelegate(parent),
mView(parent)
{
}
/************************************************
************************************************/
QSize PageSelectWidgetItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QVariant value = index.data(Qt::SizeHintRole);
if (value.isValid())
return qvariant_cast<QSize>(value);
//all items should have unified width
QStyleOptionViewItem opt = option;
initStyleOption(&opt, index);
const QWidget *widget = option.widget;
QStyle *style = widget ? widget->style() : QApplication::style();
QSize size = style->sizeFromContents(QStyle::CT_ItemViewItem, &opt, QSize(), widget);
//NOTE: this margin logic follows code in QCommonStylePrivate::viewItemLayout()
const int margin = style->pixelMetric(QStyle::PM_FocusFrameHMargin, &option, option.widget) + 1;
// Find the extra vertical gap by subtracting the height of the text when wrapped within
// the default size from the height of the text when wrapped within our max. width.
const QRect R1 = mView->fontMetrics().boundingRect(QRect(0, 0, size.width() - 2 * margin, 0),
Qt::AlignLeft | Qt::TextWordWrap, opt.text);
const QRect R2 = mView->fontMetrics().boundingRect(QRect(0, 0, mView->getWrappedTextWidth(), 0),
Qt::AlignLeft | Qt::TextWordWrap, opt.text);
// compensate for the vertical gap
size.rheight() -= qAbs(R1.height() - R2.height());
//considering the icon size too
size.setWidth(qMax(mView->maxTextWidth(), option.decorationSize.width()));
// adding the margin is good but not necessary because it is already added
size.rwidth() += 2 * margin;
size.rheight() += margin; // only at the bottom
return size;
}
/************************************************
************************************************/
PageSelectWidget::PageSelectWidget(QWidget *parent) :
QListWidget(parent)
, mMaxTextWidth(0)
{
mWrappedTextWidth = fontMetrics().averageCharWidth() * 13; // max. 13 characters
setSelectionRectVisible(false);
setViewMode(IconMode);
setSpacing(2);
setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding);
setWordWrap(true);
setDragEnabled(NoDragDrop);
setEditTriggers(NoEditTriggers);
setTextElideMode(Qt::ElideNone);
setContentsMargins(0, 0, 0, 0);
setItemDelegate(new PageSelectWidgetItemDelegate(this));
connect(model(), &QAbstractItemModel::rowsInserted, this, &PageSelectWidget::updateMaxTextWidth);
connect(model(), &QAbstractItemModel::rowsRemoved, this, &PageSelectWidget::updateMaxTextWidth);
connect(model(), &QAbstractItemModel::dataChanged, this, &PageSelectWidget::updateMaxTextWidth);
}
/************************************************
************************************************/
PageSelectWidget::~PageSelectWidget() = default;
/************************************************
************************************************/
int PageSelectWidget::maxTextWidth() const
{
return mMaxTextWidth;
}
/************************************************
************************************************/
QSize PageSelectWidget::viewportSizeHint() const
{
const int spacing2 = spacing() * 2;
QSize size{sizeHintForColumn(0) + spacing2, (sizeHintForRow(0) + spacing2) * count()};
auto vScrollbar = verticalScrollBar();
if (vScrollbar
&& vScrollbar->isVisible()
&& !vScrollbar->style()->styleHint(QStyle::SH_ScrollBar_Transient, nullptr, vScrollbar))
{
size.rwidth() += verticalScrollBar()->sizeHint().width();
}
return size;
}
/************************************************
************************************************/
QSize PageSelectWidget::sizeHint() const
{
const int f = 2 * frameWidth();
return viewportSizeHint() + QSize(f, f);
}
/************************************************
************************************************/
QSize PageSelectWidget::minimumSizeHint() const
{
return QSize{0, 0};
}
/************************************************
************************************************/
void PageSelectWidget::updateMaxTextWidth()
{
for(int i = count() - 1; 0 <= i; --i)
{
const QRect r = fontMetrics().boundingRect(QRect(0, 0, mWrappedTextWidth, 0),
Qt::AlignLeft | Qt::TextWordWrap, item(i)->text());
mMaxTextWidth = qMax(mMaxTextWidth, r.width());
}
}
/************************************************
************************************************/
bool PageSelectWidget::event(QEvent * event)
{
if (QEvent::StyleChange == event->type())
updateMaxTextWidth();
return QListWidget::event(event);
}