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