File indexing completed on 2025-01-05 04:35:04

0001 /* ============================================================
0002 * GreaseMonkey plugin for Falkon
0003 * Copyright (C) 2012-2017 David Rosca <nowrep@gmail.com>
0004 *
0005 * This program is free software: you can redistribute it and/or modify
0006 * it under the terms of the GNU General Public License as published by
0007 * the Free Software Foundation, either version 3 of the License, or
0008 * (at your option) any later version.
0009 *
0010 * This program is distributed in the hope that it will be useful,
0011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
0012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0013 * GNU General Public License for more details.
0014 *
0015 * You should have received a copy of the GNU General Public License
0016 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
0017 * ============================================================ */
0018 #include "gm_settingslistdelegate.h"
0019 #include "gm_script.h"
0020 
0021 #include "iconprovider.h"
0022 
0023 #include <QPainter>
0024 #include <QListWidget>
0025 #include <QApplication>
0026 #include <QtGuiVersion>
0027 
0028 GM_SettingsListDelegate::GM_SettingsListDelegate(QObject* parent)
0029     : QStyledItemDelegate(parent)
0030     , m_rowHeight(0)
0031     , m_padding(0)
0032 {
0033     m_removePixmap = IconProvider::standardIcon(QStyle::SP_DialogCloseButton).pixmap(16);
0034     m_updateIcon = IconProvider::standardIcon(QStyle::SP_BrowserReload);
0035 }
0036 
0037 int GM_SettingsListDelegate::padding() const
0038 {
0039     return m_padding;
0040 }
0041 
0042 void GM_SettingsListDelegate::paint(QPainter* painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
0043 {
0044     GM_Script *script = static_cast<GM_Script*>(index.data(Qt::UserRole + 10).value<void*>());
0045     if (!script)
0046         return;
0047 
0048     QStyleOptionViewItem opt = option;
0049     initStyleOption(&opt, index);
0050 
0051     const QWidget* w = opt.widget;
0052     const QStyle* style = w ? w->style() : QApplication::style();
0053     const int height = opt.rect.height();
0054     const int center = height / 2 + opt.rect.top();
0055 
0056     // forced to LTR, see issue#967
0057     painter->setLayoutDirection(Qt::LeftToRight);
0058 
0059     // Prepare title font
0060     QFont titleFont = opt.font;
0061     titleFont.setBold(true);
0062     titleFont.setPointSize(titleFont.pointSize() + 1);
0063 
0064     const QFontMetrics titleMetrics(titleFont);
0065     const QPalette::ColorRole colorRole = opt.state & QStyle::State_Selected ? QPalette::HighlightedText : QPalette::Text;
0066 
0067     QPalette::ColorGroup cg = opt.state & QStyle::State_Enabled ? QPalette::Normal : QPalette::Disabled;
0068     if (cg == QPalette::Normal && !(opt.state & QStyle::State_Active)) {
0069         cg = QPalette::Inactive;
0070     }
0071 
0072 #ifdef Q_OS_WIN
0073     opt.palette.setColor(QPalette::All, QPalette::HighlightedText, opt.palette.color(QPalette::Active, QPalette::Text));
0074     opt.palette.setColor(QPalette::All, QPalette::Highlight, opt.palette.base().color().darker(108));
0075 #endif
0076 
0077     QPalette textPalette = opt.palette;
0078     textPalette.setCurrentColorGroup(cg);
0079 
0080     int leftPosition = m_padding;
0081     int rightPosition = opt.rect.right() - m_padding - 16; // 16 for remove button
0082     if (!script->downloadUrl().isEmpty())
0083         rightPosition -= m_padding + 16; // 16 for update button
0084 
0085     // Draw background
0086     style->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, painter, w);
0087 
0088     // Draw checkbox
0089     const int checkboxSize = 18;
0090     const int checkboxYPos = center - (checkboxSize / 2);
0091     QStyleOptionViewItem opt2 = opt;
0092     opt2.checkState == Qt::Checked ? opt2.state |= QStyle::State_On : opt2.state |= QStyle::State_Off;
0093     QRect styleCheckBoxRect = style->subElementRect(QStyle::SE_ItemViewItemCheckIndicator, &opt2, w);
0094     opt2.rect = QRect(leftPosition, checkboxYPos, styleCheckBoxRect.width(), styleCheckBoxRect.height());
0095     style->drawPrimitive(QStyle::PE_IndicatorItemViewItemCheck, &opt2, painter, w);
0096     leftPosition = opt2.rect.right() + m_padding;
0097 
0098     // Draw icon
0099     const int iconSize = 32;
0100     const int iconYPos = center - (iconSize / 2);
0101     QRect iconRect(leftPosition, iconYPos, iconSize, iconSize);
0102     QPixmap pixmap = index.data(Qt::DecorationRole).value<QIcon>().pixmap(iconSize);
0103     if (!pixmap.isNull()) {
0104         painter->drawPixmap(iconRect, pixmap);
0105         leftPosition = iconRect.right() + m_padding;
0106     } else {
0107         leftPosition += m_padding;
0108     }
0109 
0110     // Draw script name
0111     const QString name = index.data(Qt::DisplayRole).toString();
0112     const int leftTitleEdge = leftPosition + 2;
0113     const int rightTitleEdge = rightPosition - m_padding;
0114     const int leftPosForVersion = titleMetrics.horizontalAdvance(name) + m_padding;
0115     QRect nameRect(leftTitleEdge, opt.rect.top() + m_padding, rightTitleEdge - leftTitleEdge, titleMetrics.height());
0116     painter->setFont(titleFont);
0117     style->drawItemText(painter, nameRect, Qt::AlignLeft, textPalette, true, name, colorRole);
0118 
0119     // Draw version
0120     QRect versionRect(nameRect.x() + leftPosForVersion, nameRect.y(), rightTitleEdge - leftPosForVersion, titleMetrics.height());
0121     QFont versionFont = titleFont;
0122     versionFont.setBold(false);
0123     painter->setFont(versionFont);
0124     style->drawItemText(painter, versionRect, Qt::AlignLeft, textPalette, true, script->version(), colorRole);
0125 
0126     // Draw description
0127     const int infoYPos = nameRect.bottom() + opt.fontMetrics.leading();
0128     QRect infoRect(nameRect.x(), infoYPos, nameRect.width(), opt.fontMetrics.height());
0129     const QString info = opt.fontMetrics.elidedText(script->description(), Qt::ElideRight, infoRect.width());
0130     painter->setFont(opt.font);
0131     style->drawItemText(painter, infoRect, Qt::TextSingleLine | Qt::AlignLeft, textPalette, true, info, colorRole);
0132 
0133     // Draw update button
0134     if (!script->downloadUrl().isEmpty()) {
0135         const int updateIconSize = 16;
0136         const int updateIconYPos = center - (updateIconSize / 2);
0137         const QPixmap updatePixmap = m_updateIcon.pixmap(16, script->isUpdating() ? QIcon::Disabled : QIcon::Normal);
0138         QRect updateIconRect(rightPosition, updateIconYPos, updateIconSize, updateIconSize);
0139         painter->drawPixmap(updateIconRect, updatePixmap);
0140         rightPosition += m_padding + 16;
0141     }
0142 
0143     // Draw remove button
0144     const int removeIconSize = 16;
0145     const int removeIconYPos = center - (removeIconSize / 2);
0146     QRect removeIconRect(rightPosition, removeIconYPos, removeIconSize, removeIconSize);
0147     painter->drawPixmap(removeIconRect, m_removePixmap);
0148 }
0149 
0150 QSize GM_SettingsListDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
0151 {
0152     Q_UNUSED(index)
0153 
0154     if (!m_rowHeight) {
0155         QStyleOptionViewItem opt(option);
0156         initStyleOption(&opt, index);
0157 
0158         const QWidget* w = opt.widget;
0159         const QStyle* style = w ? w->style() : QApplication::style();
0160         const int padding = style->pixelMetric(QStyle::PM_FocusFrameHMargin, nullptr) + 1;
0161 
0162         QFont titleFont = opt.font;
0163         titleFont.setBold(true);
0164         titleFont.setPointSize(titleFont.pointSize() + 1);
0165 
0166         m_padding = padding > 5 ? padding : 5;
0167 
0168         const QFontMetrics titleMetrics(titleFont);
0169 
0170         m_rowHeight = 2 * m_padding + opt.fontMetrics.leading() + opt.fontMetrics.height() + titleMetrics.height();
0171     }
0172 
0173     return QSize(200, m_rowHeight);
0174 }