File indexing completed on 2024-05-12 04:19:41
0001 // vim: set tabstop=4 shiftwidth=4 expandtab: 0002 /* 0003 Gwenview: an image viewer 0004 Copyright 2011 Aurélien Gâteau <agateau@kde.org> 0005 0006 This program is free software; you can redistribute it and/or 0007 modify it under the terms of the GNU General Public License 0008 as published by the Free Software Foundation; either version 2 0009 of the License, or (at your option) any later version. 0010 0011 This program is distributed in the hope that it will be useful, 0012 but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0014 GNU General Public License for more details. 0015 0016 You should have received a copy of the GNU General Public License 0017 along with this program; if not, write to the Free Software 0018 Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA. 0019 0020 */ 0021 // Self 0022 #include "hud/hudbutton.h" 0023 0024 // Local 0025 #include "gwenview_lib_debug.h" 0026 #include <hud/hudtheme.h> 0027 0028 // KF 0029 #include <KIconLoader> 0030 0031 // Qt 0032 #include <QAction> 0033 #include <QFontDatabase> 0034 #include <QFontMetrics> 0035 #include <QGraphicsSceneEvent> 0036 #include <QIcon> 0037 #include <QPainter> 0038 #include <QStyle> 0039 #include <QStyleOptionGraphicsItem> 0040 0041 namespace Gwenview 0042 { 0043 struct LayoutInfo { 0044 QRect iconRect; 0045 QRect textRect; 0046 QSize size; 0047 }; 0048 0049 struct HudButtonPrivate { 0050 HudButton *q = nullptr; 0051 QAction *mAction = nullptr; 0052 0053 QPalette mDarkPalette; 0054 QPixmap mLightIcon; 0055 KIconLoader::Group mIconGroup; 0056 QString mText; 0057 0058 bool mIsDown; 0059 0060 void initLayoutInfo(LayoutInfo *info, const QSizeF &constraint) 0061 { 0062 HudTheme::RenderInfo renderInfo = HudTheme::renderInfo(HudTheme::ButtonWidget); 0063 const int padding = renderInfo.padding; 0064 QSize minInnerSize = constraint.toSize() - QSize(2 * padding, 2 * padding); 0065 0066 if (!mLightIcon.isNull()) { 0067 const int size = KIconLoader::global()->currentSize(mIconGroup); 0068 info->iconRect = QRect(padding, padding, size, qMax(size, minInnerSize.height())); 0069 minInnerSize.rwidth() -= size; 0070 } 0071 if (!mText.isEmpty()) { 0072 const QFont font = QFontDatabase::systemFont(QFontDatabase::GeneralFont); 0073 QFontMetrics fm(font); 0074 const QSize size = fm.size(0, mText).expandedTo(minInnerSize); 0075 info->textRect = QRect(padding, padding, size.width(), size.height()); 0076 if (!info->iconRect.isNull()) { 0077 info->textRect.translate(info->iconRect.right(), 0); 0078 } 0079 } 0080 0081 const QRectF rect = info->iconRect | info->textRect; 0082 info->size = QSize(rect.right() + padding, rect.bottom() + padding); 0083 } 0084 0085 void initFromAction() 0086 { 0087 Q_ASSERT(mAction); 0088 q->setIcon(mAction->icon()); 0089 q->setText(mAction->text()); 0090 } 0091 }; 0092 0093 HudButton::HudButton(QGraphicsItem *parent) 0094 : QGraphicsWidget(parent) 0095 , d(new HudButtonPrivate) 0096 { 0097 d->q = this; 0098 d->mAction = nullptr; 0099 d->mIsDown = false; 0100 0101 // Palette to use for generating light icon. All we need is a light foreground. 0102 d->mDarkPalette = palette(); 0103 d->mDarkPalette.setColor(QPalette::WindowText, Qt::white); 0104 d->mIconGroup = KIconLoader::Small; 0105 0106 setCursor(Qt::ArrowCursor); 0107 setAcceptHoverEvents(true); 0108 } 0109 0110 HudButton::~HudButton() 0111 { 0112 delete d; 0113 } 0114 0115 void HudButton::setIcon(const QIcon &icon) 0116 { 0117 // Since the HUD is always drawn with a dark theme, we need to make sure 0118 // the icon is light, in order to contrast. We then cache this light icon 0119 // to avoid setting a custom palette on KIconLoader repeatedly. 0120 KIconLoader::global()->setCustomPalette(d->mDarkPalette); 0121 d->mLightIcon = icon.pixmap(KIconLoader::global()->currentSize(d->mIconGroup)); 0122 KIconLoader::global()->resetPalette(); 0123 updateGeometry(); 0124 } 0125 0126 void HudButton::setText(const QString &text) 0127 { 0128 d->mText = text; 0129 updateGeometry(); 0130 } 0131 0132 void HudButton::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *) 0133 { 0134 HudTheme::State state; 0135 if (option->state.testFlag(QStyle::State_MouseOver)) { 0136 state = d->mIsDown ? HudTheme::DownState : HudTheme::MouseOverState; 0137 } else { 0138 state = HudTheme::NormalState; 0139 } 0140 HudTheme::RenderInfo renderInfo = HudTheme::renderInfo(HudTheme::ButtonWidget, state); 0141 0142 painter->setPen(renderInfo.borderPen); 0143 painter->setBrush(renderInfo.bgBrush); 0144 painter->setRenderHint(QPainter::Antialiasing); 0145 painter->drawRoundedRect(boundingRect().adjusted(.5, .5, -.5, -.5), renderInfo.borderRadius, renderInfo.borderRadius); 0146 0147 LayoutInfo info; 0148 d->initLayoutInfo(&info, size()); 0149 0150 if (!d->mLightIcon.isNull()) { 0151 painter->drawPixmap(info.iconRect.topLeft(), d->mLightIcon); 0152 } 0153 if (!d->mText.isEmpty()) { 0154 painter->setPen(renderInfo.textPen); 0155 painter->drawText(info.textRect, Qt::AlignCenter, d->mText); 0156 } 0157 } 0158 0159 QSizeF HudButton::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const 0160 { 0161 LayoutInfo info; 0162 d->initLayoutInfo(&info, constraint); 0163 if (which == Qt::MinimumSize || which == Qt::PreferredSize) { 0164 return info.size; 0165 } else { 0166 return constraint.expandedTo(info.size); 0167 } 0168 } 0169 0170 void HudButton::mousePressEvent(QGraphicsSceneMouseEvent *) 0171 { 0172 d->mIsDown = true; 0173 update(); 0174 } 0175 0176 void HudButton::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) 0177 { 0178 d->mIsDown = false; 0179 update(); 0180 if (boundingRect().contains(event->pos())) { 0181 Q_EMIT clicked(); 0182 } 0183 } 0184 0185 void HudButton::setDefaultAction(QAction *action) 0186 { 0187 if (action != d->mAction) { 0188 d->mAction = action; 0189 if (!actions().contains(action)) { 0190 addAction(action); 0191 } 0192 d->initFromAction(); 0193 connect(this, SIGNAL(clicked()), d->mAction, SLOT(trigger())); 0194 } 0195 } 0196 0197 bool HudButton::event(QEvent *event) 0198 { 0199 if (event->type() == QEvent::ActionChanged) { 0200 d->initFromAction(); 0201 } 0202 return QGraphicsWidget::event(event); 0203 } 0204 0205 } // namespace 0206 0207 #include "moc_hudbutton.cpp"