File indexing completed on 2022-07-03 17:05:47
0001 /* 0002 SPDX-FileCopyrightText: 2001-2013 Evan Teran <evan.teran@gmail.com> 0003 SPDX-FileCopyrightText: 1996-2000 Bernd Johannes Wuebben <wuebben@kde.org> 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #include "kcalc_button.h" 0009 0010 #include <QAbstractTextDocumentLayout> 0011 #include <QApplication> 0012 #include <QPainter> 0013 #include <QStyleOptionButton> 0014 #include <QTextDocument> 0015 0016 //------------------------------------------------------------------------------ 0017 // Name: KCalcButton 0018 // Desc: constructor 0019 //------------------------------------------------------------------------------ 0020 KCalcButton::KCalcButton(QWidget *parent) 0021 : QPushButton(parent) 0022 , mode_flags_(ModeNormal) 0023 , size_() 0024 { 0025 setAcceptDrops(true); // allow color drops 0026 setFocusPolicy(Qt::TabFocus); 0027 setAutoDefault(false); 0028 0029 // use preferred size policy for vertical 0030 setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred); 0031 setAttribute(Qt::WA_LayoutUsesWidgetRect); 0032 } 0033 0034 //------------------------------------------------------------------------------ 0035 // Name: KCalcButton 0036 // Desc: constructor 0037 //------------------------------------------------------------------------------ 0038 KCalcButton::KCalcButton(const QString &label, QWidget *parent, const QString &tooltip) 0039 : QPushButton(label, parent) 0040 , mode_flags_(ModeNormal) 0041 , size_() 0042 { 0043 setAutoDefault(false); 0044 addMode(ModeNormal, label, tooltip); 0045 0046 // use preferred size policy for vertical 0047 setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred); 0048 setAttribute(Qt::WA_LayoutUsesWidgetRect); 0049 } 0050 0051 //------------------------------------------------------------------------------ 0052 // Name: addMode 0053 // Desc: 0054 //------------------------------------------------------------------------------ 0055 void KCalcButton::addMode(ButtonModeFlags mode, const QString &label, const QString &tooltip) 0056 { 0057 if (mode_.contains(mode)) { 0058 mode_.remove(mode); 0059 } 0060 0061 mode_[mode] = ButtonMode(label, tooltip); 0062 calcSizeHint(); 0063 0064 // Need to put each button into default mode first 0065 if (mode == ModeNormal) { 0066 slotSetMode(ModeNormal, true); 0067 } 0068 } 0069 0070 //------------------------------------------------------------------------------ 0071 // Name: slotSetMode 0072 // Desc: 0073 //------------------------------------------------------------------------------ 0074 void KCalcButton::slotSetMode(ButtonModeFlags mode, bool flag) 0075 { 0076 ButtonModeFlags new_mode; 0077 0078 if (flag) { // if the specified mode is to be set (i.e. flag = true) 0079 new_mode = ButtonModeFlags(mode_flags_ | mode); 0080 } else if (mode_flags_ & mode) { // if the specified mode is to be cleared (i.e. flag = false) 0081 new_mode = ButtonModeFlags(mode_flags_ - mode); 0082 } else { 0083 return; // nothing to do 0084 } 0085 0086 if (mode_.contains(new_mode)) { 0087 // save shortcut, because setting label erases it 0088 QKeySequence current_shortcut = shortcut(); 0089 0090 setText(mode_[new_mode].label); 0091 this->setToolTip(mode_[new_mode].tooltip); 0092 mode_flags_ = new_mode; 0093 0094 // restore shortcut 0095 setShortcut(current_shortcut); 0096 } 0097 0098 // this is necessary for people pressing CTRL and changing mode at 0099 // the same time... 0100 if (show_shortcut_mode_) { 0101 slotSetAccelDisplayMode(true); 0102 } 0103 0104 update(); 0105 } 0106 0107 //------------------------------------------------------------------------------ 0108 // Name: slotSetAccelDisplayMode 0109 // Desc: 0110 //------------------------------------------------------------------------------ 0111 void KCalcButton::slotSetAccelDisplayMode(bool flag) 0112 { 0113 show_shortcut_mode_ = flag; 0114 0115 // save shortcut, because setting label erases it 0116 QKeySequence current_shortcut = shortcut(); 0117 0118 if (flag) { 0119 setText(shortcut().toString(QKeySequence::NativeText)); 0120 } else { 0121 setText(mode_[mode_flags_].label); 0122 } 0123 0124 // restore shortcut 0125 setShortcut(current_shortcut); 0126 update(); 0127 } 0128 0129 //------------------------------------------------------------------------------ 0130 // Name: paintEvent 0131 // Desc: draws the button 0132 //------------------------------------------------------------------------------ 0133 void KCalcButton::paintEvent(QPaintEvent *) 0134 { 0135 QPainter p(this); 0136 QStyleOptionButton option; 0137 initStyleOption(&option); 0138 const bool is_down = isDown() || isChecked(); 0139 const int x_offset = is_down ? style()->pixelMetric(QStyle::PM_ButtonShiftHorizontal, &option, this) : 0; 0140 const int y_offset = is_down ? style()->pixelMetric(QStyle::PM_ButtonShiftVertical, &option, this) : 0; 0141 0142 // draw bevel 0143 style()->drawControl(QStyle::CE_PushButtonBevel, &option, &p, this); 0144 0145 // draw label... 0146 p.save(); 0147 0148 // rant: Qt4 needs QSimpleRichText, dammit! 0149 QTextDocument doc; 0150 QAbstractTextDocumentLayout::PaintContext context; 0151 doc.setHtml(QLatin1String("<center>") + text() + QLatin1String("</center>")); 0152 doc.setDefaultFont(font()); 0153 context.palette = palette(); 0154 QColor color = text_color_; 0155 if (!isEnabled()) { 0156 color.setAlphaF(0.6); 0157 } 0158 context.palette.setColor(QPalette::Text, color); 0159 0160 p.translate((width() / 2 - doc.size().width() / 2) + x_offset, (height() / 2 - doc.size().height() / 2) + y_offset); 0161 doc.documentLayout()->draw(&p, context); 0162 p.restore(); 0163 0164 // draw focus 0165 if (hasFocus()) { 0166 QStyleOptionFocusRect fropt; 0167 fropt.QStyleOption::operator=(option); 0168 fropt.rect = style()->subElementRect(QStyle::SE_PushButtonFocusRect, &option, this); 0169 style()->drawPrimitive(QStyle::PE_FrameFocusRect, &fropt, &p, this); 0170 } 0171 } 0172 0173 //------------------------------------------------------------------------------ 0174 // Name: sizeHint 0175 // Desc: 0176 //------------------------------------------------------------------------------ 0177 QSize KCalcButton::sizeHint() const 0178 { 0179 // reimplemented to provide a smaller button 0180 return size_; 0181 } 0182 0183 //------------------------------------------------------------------------------ 0184 // Name: calcSizeHint 0185 // Desc: 0186 //------------------------------------------------------------------------------ 0187 void KCalcButton::calcSizeHint() 0188 { 0189 int margin = style()->pixelMetric(QStyle::PM_ButtonMargin, nullptr, this); 0190 0191 // want narrower margin than normal 0192 margin = qMax(margin / 2, 3); 0193 0194 // simply use font size of a single letter 0195 size_ = fontMetrics().size(0, QStringLiteral("M")); 0196 0197 size_ += QSize(margin * 2, margin * 2); 0198 } 0199 0200 //------------------------------------------------------------------------------ 0201 // Name: setFont 0202 // Desc: 0203 //------------------------------------------------------------------------------ 0204 void KCalcButton::setFont(const QFont &fnt) 0205 { 0206 QPushButton::setFont(fnt); 0207 calcSizeHint(); 0208 } 0209 0210 //------------------------------------------------------------------------------ 0211 // Name: setTextColor 0212 // Desc: 0213 //------------------------------------------------------------------------------ 0214 void KCalcButton::setTextColor(const QColor &color) 0215 { 0216 text_color_ = color; 0217 update(); 0218 } 0219 0220 //------------------------------------------------------------------------------ 0221 // Name: setText 0222 // Desc: 0223 //------------------------------------------------------------------------------ 0224 void KCalcButton::setText(const QString &text) 0225 { 0226 QPushButton::setText(text); 0227 0228 // normal mode may not have been explicitly set 0229 if (mode_[ModeNormal].label.isEmpty()) { 0230 mode_[ModeNormal].label = text; 0231 } 0232 0233 calcSizeHint(); 0234 } 0235 0236 //------------------------------------------------------------------------------ 0237 // Name: setToolTip 0238 // Desc: 0239 //------------------------------------------------------------------------------ 0240 void KCalcButton::setToolTip(const QString &tip) 0241 { 0242 QPushButton::setToolTip(tip); 0243 0244 // normal mode may not have been explicitly set 0245 if (mode_[ModeNormal].tooltip.isEmpty()) { 0246 mode_[ModeNormal].tooltip = tip; 0247 } 0248 }