File indexing completed on 2024-05-12 16:01:27

0001 /*
0002  *  SPDX-FileCopyrightText: 2009 Cyrille Berger <cberger@cberger.net>
0003  *  SPDX-FileCopyrightText: 2011 Silvio Heinrich <plassy@web.de>
0004  *  SPDX-FileCopyrightText: 2014 Mohit Goyal <mohit.bits2011@gmail.com>
0005  *
0006  *  SPDX-License-Identifier: LGPL-2.1-or-later
0007  */
0008 
0009 #include "kis_categorized_item_delegate.h"
0010 #include "kis_categorized_list_model.h"
0011 
0012 #include <QPainter>
0013 #include <QStyle>
0014 #include <QStyleOptionMenuItem>
0015 #include <QStyleOptionViewItem>
0016 #include <QApplication>
0017 #include <QTransform>
0018 
0019 #include <KoIcon.h>
0020 
0021 #include <kis_icon.h>
0022 #include "kis_debug.h"
0023 
0024 KisCategorizedItemDelegate::KisCategorizedItemDelegate(QObject *parent)
0025     : QStyledItemDelegate(parent),
0026       m_minimumItemHeight(0)
0027 {
0028 }
0029 
0030 void KisCategorizedItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
0031 {
0032     painter->resetTransform();
0033 
0034     if(!index.data(__CategorizedListModelBase::IsHeaderRole).toBool()) {
0035         QStyleOptionViewItem sovi(option);
0036 
0037         if (index.data(__CategorizedListModelBase::isLockableRole).toBool()) {
0038 
0039             const int iconSize = qMax(16, m_minimumItemHeight - 2);
0040             bool locked = index.data(__CategorizedListModelBase::isLockedRole).toBool();
0041 
0042 
0043             QIcon icon = locked ? KisIconUtils::loadIcon(koIconName("layer-locked")) : KisIconUtils::loadIcon(koIconName("layer-unlocked"));
0044 
0045             // to be able to make an icon more transparent. we need to create a new image
0046             // and use the QPainter to make a more transparent version of it.
0047             QImage image(iconSize, iconSize, QImage::Format_ARGB32_Premultiplied);
0048             image.fill(Qt::transparent); // needs to happen, otherwise 'junk' pixels are used (looks bad)
0049 
0050             QPainter p(&image);
0051             p.setCompositionMode(QPainter::CompositionMode_Source);
0052 
0053 
0054             // make unlocked icons more hidden
0055             if (locked) {
0056                 p.setOpacity(1.0);
0057             } else {
0058                 p.setOpacity(0.14);
0059             }
0060 
0061             p.drawPixmap(0, 0, icon.pixmap(iconSize, QIcon::Normal) );
0062             p.end();
0063 
0064             icon = QIcon( QPixmap::fromImage(image) ); // the new icon is ready
0065 
0066 
0067 
0068             sovi.decorationPosition = QStyleOptionViewItem::Right;
0069             sovi.decorationAlignment = Qt::AlignRight;
0070             sovi.decorationSize = QSize(iconSize, iconSize);
0071             sovi.features |= QStyleOptionViewItem::HasDecoration;
0072             sovi.icon = icon;
0073 
0074         }
0075 
0076         QStyledItemDelegate::paint(painter, sovi, index);
0077         painter->setOpacity(1);
0078     }
0079     else {
0080         QPalette palette = QApplication::palette();
0081         if(option.state & QStyle::State_MouseOver)
0082             painter->fillRect(option.rect, palette.midlight());
0083         else
0084             painter->fillRect(option.rect, palette.button());
0085 
0086         painter->setBrush(palette.buttonText());
0087         painter->drawText(option.rect, index.data().toString(), QTextOption(Qt::AlignVCenter|Qt::AlignHCenter));
0088 
0089         paintTriangle(
0090             painter,
0091             option.rect.x(),
0092             option.rect.y(),
0093             option.rect.height(),
0094             !index.data(__CategorizedListModelBase::ExpandCategoryRole).toBool()
0095         );
0096     }
0097     painter->resetTransform();
0098 }
0099 
0100 QSize KisCategorizedItemDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const
0101 {
0102     //on first calling this calculates the minimal height of the items
0103     if (m_minimumItemHeight == 0) {
0104         for(int i=0; i<index.model()->rowCount(); i++) {
0105             QSize indexSize = QStyledItemDelegate::sizeHint(option, index.model()->index(i, 0));
0106             m_minimumItemHeight = qMax(m_minimumItemHeight, indexSize.height());
0107 
0108             /**
0109              * Make all the items, including the ones having
0110              * checkboxes look the same.
0111              */
0112             QStyle *style = QApplication::style();
0113             QStyleOptionButton so;
0114             QSize size = style->sizeFromContents(QStyle::CT_CheckBox, &so, QSize(), 0);
0115 
0116             m_minimumItemHeight = qMax(size.height(), m_minimumItemHeight);
0117         }
0118     }
0119 
0120     int width = QStyledItemDelegate::sizeHint(option, index).width();
0121 
0122     if (index.data(__CategorizedListModelBase::isLockableRole).toBool()) {
0123         width += m_minimumItemHeight;
0124     }
0125 
0126     return QSize(width, m_minimumItemHeight);
0127 }
0128 
0129 void KisCategorizedItemDelegate::paintTriangle(QPainter* painter, qint32 x, qint32 y, qint32 size, bool rotate) const
0130 {
0131     QPolygonF triangle;
0132     triangle.push_back(QPointF(-0.2,-0.2));
0133     triangle.push_back(QPointF( 0.2,-0.2));
0134     triangle.push_back(QPointF( 0.0, 0.2));
0135 
0136     QTransform transform;
0137     transform.translate(x + size/2, y + size/2);
0138     transform.scale(size, size);
0139 
0140     if(rotate)
0141         transform.rotate(-90);
0142 
0143     QPalette palette = QApplication::palette();
0144     painter->setBrush(palette.buttonText());
0145     painter->drawPolygon(transform.map(triangle));
0146 }
0147