kcalc_button.cpp 7.61 KB
Newer Older
1
/*
2
3
    SPDX-FileCopyrightText: 2001-2013 Evan Teran <evan.teran@gmail.com>
    SPDX-FileCopyrightText: 1996-2000 Bernd Johannes Wuebben <wuebben@kde.org>
4

5
    SPDX-License-Identifier: GPL-2.0-or-later
6
7
*/

David Johnson's avatar
David Johnson committed
8
9
#include "kcalc_button.h"

David Johnson's avatar
David Johnson committed
10
#include <QAbstractTextDocumentLayout>
11
#include <QApplication>
12
#include <QPainter>
David Johnson's avatar
David Johnson committed
13
14
#include <QStyleOptionButton>
#include <QTextDocument>
15

16
//------------------------------------------------------------------------------
17
// Name: KCalcButton
18
19
// Desc: constructor
//------------------------------------------------------------------------------
20
21
22
23
24
25
26
27
28
29
30
31
KCalcButton::KCalcButton(QWidget *parent)
    : QPushButton(parent)
    , mode_flags_(ModeNormal)
    , size_()
{
    setAcceptDrops(true); // allow color drops
    setFocusPolicy(Qt::TabFocus);
    setAutoDefault(false);

    // use preferred size policy for vertical
    setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred);
    setAttribute(Qt::WA_LayoutUsesWidgetRect);
32
}
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
33

34
//------------------------------------------------------------------------------
35
// Name: KCalcButton
36
37
// Desc: constructor
//------------------------------------------------------------------------------
38
39
40
41
42
43
44
45
46
47
48
KCalcButton::KCalcButton(const QString &label, QWidget *parent, const QString &tooltip)
    : QPushButton(label, parent)
    , mode_flags_(ModeNormal)
    , size_()
{
    setAutoDefault(false);
    addMode(ModeNormal, label, tooltip);

    // use preferred size policy for vertical
    setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred);
    setAttribute(Qt::WA_LayoutUsesWidgetRect);
49
50
}

51
//------------------------------------------------------------------------------
52
// Name: addMode
53
// Desc:
54
//------------------------------------------------------------------------------
55
56
57
58
59
60
61
62
63
64
65
66
67
void KCalcButton::addMode(ButtonModeFlags mode, const QString &label, const QString &tooltip)
{
    if (mode_.contains(mode)) {
        mode_.remove(mode);
    }

    mode_[mode] = ButtonMode(label, tooltip);
    calcSizeHint();

    // Need to put each button into default mode first
    if (mode == ModeNormal) {
        slotSetMode(ModeNormal, true);
    }
68
}
69

70
//------------------------------------------------------------------------------
71
// Name: slotSetMode
72
// Desc:
73
//------------------------------------------------------------------------------
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
void KCalcButton::slotSetMode(ButtonModeFlags mode, bool flag)
{
    ButtonModeFlags new_mode;

    if (flag) { // if the specified mode is to be set (i.e. flag = true)
        new_mode = ButtonModeFlags(mode_flags_ | mode);
    } else if (mode_flags_ && mode) { // if the specified mode is to be cleared (i.e. flag = false)
        new_mode = ButtonModeFlags(mode_flags_ - mode);
    } else {
        return; // nothing to do
    }

    if (mode_.contains(new_mode)) {
        // save shortcut, because setting label erases it
        QKeySequence current_shortcut = shortcut();

        setText(mode_[new_mode].label);
        this->setToolTip(mode_[new_mode].tooltip);
        mode_flags_ = new_mode;

        // restore shortcut
        setShortcut(current_shortcut);
    }

    // this is necessary for people pressing CTRL and changing mode at
    // the same time...
    if (show_shortcut_mode_) {
        slotSetAccelDisplayMode(true);
    }

    update();
105
106
}

107
//------------------------------------------------------------------------------
108
// Name: slotSetAccelDisplayMode
109
// Desc:
110
//------------------------------------------------------------------------------
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
void KCalcButton::slotSetAccelDisplayMode(bool flag)
{
    show_shortcut_mode_ = flag;

    // save shortcut, because setting label erases it
    QKeySequence current_shortcut = shortcut();

    if (flag) {
        setText(shortcut().toString(QKeySequence::NativeText));
    } else {
        setText(mode_[mode_flags_].label);
    }

    // restore shortcut
    setShortcut(current_shortcut);
    update();
127
128
}

129
//------------------------------------------------------------------------------
130
// Name: paintEvent
131
132
// Desc: draws the button
//------------------------------------------------------------------------------
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
void KCalcButton::paintEvent(QPaintEvent *)
{
    QPainter p(this);
    QStyleOptionButton option;
    initStyleOption(&option);
    const bool is_down = isDown() || isChecked();
    const int x_offset = is_down ? style()->pixelMetric(QStyle::PM_ButtonShiftHorizontal, &option, this) : 0;
    const int y_offset = is_down ? style()->pixelMetric(QStyle::PM_ButtonShiftVertical, &option, this) : 0;

    // draw bevel
    style()->drawControl(QStyle::CE_PushButtonBevel, &option, &p, this);

    // draw label...
    p.save();

    // rant: Qt4 needs QSimpleRichText, dammit!
    QTextDocument doc;
    QAbstractTextDocumentLayout::PaintContext context;
    doc.setHtml(QLatin1String("<center>") + text() + QLatin1String("</center>"));
    doc.setDefaultFont(font());
    context.palette = palette();
    QColor color = text_color_;
    if (!isEnabled()) {
        color.setAlphaF(0.6);
    }
    context.palette.setColor(QPalette::Text, color);

    p.translate((width() / 2 - doc.size().width() / 2) + x_offset, (height() / 2 - doc.size().height() / 2) + y_offset);
    doc.documentLayout()->draw(&p, context);
    p.restore();

    // draw focus
    if (hasFocus()) {
        QStyleOptionFocusRect fropt;
        fropt.QStyleOption::operator=(option);
        fropt.rect = style()->subElementRect(QStyle::SE_PushButtonFocusRect, &option, this);
        style()->drawPrimitive(QStyle::PE_FrameFocusRect, &fropt, &p, this);
    }
171
172
}

173
//------------------------------------------------------------------------------
174
// Name: sizeHint
175
// Desc:
176
//------------------------------------------------------------------------------
177
178
179
180
QSize KCalcButton::sizeHint() const
{
    // reimplemented to provide a smaller button
    return size_;
181
182
}

183
//------------------------------------------------------------------------------
184
// Name: calcSizeHint
185
// Desc:
186
//------------------------------------------------------------------------------
187
188
void KCalcButton::calcSizeHint()
{
189
    int margin = style()->pixelMetric(QStyle::PM_ButtonMargin, nullptr, this);
190

Marius Pa's avatar
Marius Pa committed
191
    // want narrower margin than normal
192
193
    margin = qMax(margin / 2, 3);

194
195
    // simply use font size of a single letter
    size_ = fontMetrics().size(0, QStringLiteral("M"));
196
197

    size_ += QSize(margin * 2, margin * 2);
David Johnson's avatar
GUI:    
David Johnson committed
198
199
}

200
//------------------------------------------------------------------------------
201
// Name: setFont
202
// Desc:
203
//------------------------------------------------------------------------------
204
205
206
207
void KCalcButton::setFont(const QFont &fnt)
{
    QPushButton::setFont(fnt);
    calcSizeHint();
208
209
}

210
211
//------------------------------------------------------------------------------
// Name: setTextColor
212
// Desc:
213
//------------------------------------------------------------------------------
214
215
216
217
void KCalcButton::setTextColor(const QColor &color)
{
    text_color_ = color;
    update();
218
219
}

220
//------------------------------------------------------------------------------
221
// Name: setText
222
// Desc:
223
//------------------------------------------------------------------------------
224
225
226
void KCalcButton::setText(const QString &text)
{
    QPushButton::setText(text);
227

228
229
230
231
    // normal mode may not have been explicitly set
    if (mode_[ModeNormal].label.isEmpty()) {
        mode_[ModeNormal].label = text;
    }
232

233
    calcSizeHint();
234
235
}

236
//------------------------------------------------------------------------------
237
// Name: setToolTip
238
// Desc:
239
//------------------------------------------------------------------------------
240
241
242
243
244
245
246
247
void KCalcButton::setToolTip(const QString &tip)
{
    QPushButton::setToolTip(tip);

    // normal mode may not have been explicitly set
    if (mode_[ModeNormal].tooltip.isEmpty()) {
        mode_[ModeNormal].tooltip = tip;
    }
248
}