Changeset View
Changeset View
Standalone View
Standalone View
src/kmessagewidget.cpp
Show All 29 Lines | |||||
30 | #include <QStyleOption> | 30 | #include <QStyleOption> | ||
31 | #include <QTimeLine> | 31 | #include <QTimeLine> | ||
32 | #include <QToolButton> | 32 | #include <QToolButton> | ||
33 | #include <QStyle> | 33 | #include <QStyle> | ||
34 | #include <QGuiApplication> | 34 | #include <QGuiApplication> | ||
35 | //--------------------------------------------------------------------- | 35 | //--------------------------------------------------------------------- | ||
36 | // KMessageWidgetPrivate | 36 | // KMessageWidgetPrivate | ||
37 | //--------------------------------------------------------------------- | 37 | //--------------------------------------------------------------------- | ||
38 | | ||||
39 | constexpr int borderSize = 2; | ||||
cfeck: Does it need to be `static` to avoid an external symbol? | |||||
I don't think so:
davidre: I don't think so:
>internal linkage
>[...]
>variables, variable templates (since C++14)… | |||||
40 | | ||||
38 | class KMessageWidgetPrivate | 41 | class KMessageWidgetPrivate | ||
39 | { | 42 | { | ||
40 | public: | 43 | public: | ||
41 | void init(KMessageWidget *); | 44 | void init(KMessageWidget *); | ||
42 | 45 | | |||
43 | KMessageWidget *q; | 46 | KMessageWidget *q; | ||
44 | QFrame *content = nullptr; | | |||
45 | QLabel *iconLabel = nullptr; | 47 | QLabel *iconLabel = nullptr; | ||
46 | QLabel *textLabel = nullptr; | 48 | QLabel *textLabel = nullptr; | ||
47 | QToolButton *closeButton = nullptr; | 49 | QToolButton *closeButton = nullptr; | ||
48 | QTimeLine *timeLine = nullptr; | 50 | QTimeLine *timeLine = nullptr; | ||
49 | QIcon icon; | 51 | QIcon icon; | ||
50 | bool ignoreShowEventDoingAnimatedShow = false; | 52 | bool ignoreShowEventDoingAnimatedShow = false; | ||
51 | 53 | | |||
52 | KMessageWidget::MessageType messageType; | 54 | KMessageWidget::MessageType messageType; | ||
53 | bool wordWrap; | 55 | bool wordWrap; | ||
54 | QList<QToolButton *> buttons; | 56 | QList<QToolButton *> buttons; | ||
55 | QPixmap contentSnapShot; | | |||
56 | 57 | | |||
57 | void createLayout(); | 58 | void createLayout(); | ||
58 | void applyStyleSheet(); | 59 | void setPalette(); | ||
59 | void updateSnapShot(); | | |||
60 | void updateLayout(); | 60 | void updateLayout(); | ||
61 | void slotTimeLineChanged(qreal); | 61 | void slotTimeLineChanged(qreal); | ||
62 | void slotTimeLineFinished(); | 62 | void slotTimeLineFinished(); | ||
63 | 63 | | |||
64 | int bestContentHeight() const; | 64 | int bestContentHeight() const; | ||
65 | }; | 65 | }; | ||
66 | 66 | | |||
67 | void KMessageWidgetPrivate::init(KMessageWidget *q_ptr) | 67 | void KMessageWidgetPrivate::init(KMessageWidget *q_ptr) | ||
68 | { | 68 | { | ||
69 | q = q_ptr; | 69 | q = q_ptr; | ||
70 | | ||||
71 | q->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); | | |||
72 | | ||||
73 | // Note: when changing the value 500, also update KMessageWidgetTest | 70 | // Note: when changing the value 500, also update KMessageWidgetTest | ||
74 | timeLine = new QTimeLine(500, q); | 71 | timeLine = new QTimeLine(500, q); | ||
75 | QObject::connect(timeLine, SIGNAL(valueChanged(qreal)), q, SLOT(slotTimeLineChanged(qreal))); | 72 | QObject::connect(timeLine, SIGNAL(valueChanged(qreal)), q, SLOT(slotTimeLineChanged(qreal))); | ||
76 | QObject::connect(timeLine, SIGNAL(finished()), q, SLOT(slotTimeLineFinished())); | 73 | QObject::connect(timeLine, SIGNAL(finished()), q, SLOT(slotTimeLineFinished())); | ||
77 | 74 | | |||
78 | content = new QFrame(q); | | |||
79 | content->setObjectName(QStringLiteral("contentWidget")); | | |||
80 | content->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); | | |||
81 | | ||||
82 | wordWrap = false; | 75 | wordWrap = false; | ||
83 | 76 | | |||
84 | iconLabel = new QLabel(content); | 77 | iconLabel = new QLabel(q); | ||
85 | iconLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); | 78 | iconLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); | ||
86 | iconLabel->hide(); | 79 | iconLabel->hide(); | ||
87 | 80 | | |||
88 | textLabel = new QLabel(content); | 81 | textLabel = new QLabel(q); | ||
89 | textLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); | 82 | textLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); | ||
90 | textLabel->setTextInteractionFlags(Qt::TextBrowserInteraction); | 83 | textLabel->setTextInteractionFlags(Qt::TextBrowserInteraction); | ||
91 | QObject::connect(textLabel, &QLabel::linkActivated, q, &KMessageWidget::linkActivated); | 84 | QObject::connect(textLabel, &QLabel::linkActivated, q, &KMessageWidget::linkActivated); | ||
92 | QObject::connect(textLabel, &QLabel::linkHovered, q, &KMessageWidget::linkHovered); | 85 | QObject::connect(textLabel, &QLabel::linkHovered, q, &KMessageWidget::linkHovered); | ||
93 | 86 | | |||
94 | QAction *closeAction = new QAction(q); | 87 | QAction *closeAction = new QAction(q); | ||
95 | closeAction->setText(KMessageWidget::tr("&Close")); | 88 | closeAction->setText(KMessageWidget::tr("&Close")); | ||
96 | closeAction->setToolTip(KMessageWidget::tr("Close message")); | 89 | closeAction->setToolTip(KMessageWidget::tr("Close message")); | ||
97 | QStyleOptionFrame opt; | 90 | QStyleOptionFrame opt; | ||
98 | opt.initFrom(q); | 91 | opt.initFrom(q); | ||
99 | closeAction->setIcon(q->style()->standardIcon(QStyle::SP_DialogCloseButton, &opt, q)); | 92 | closeAction->setIcon(q->style()->standardIcon(QStyle::SP_DialogCloseButton, &opt, q)); | ||
100 | 93 | | |||
101 | QObject::connect(closeAction, &QAction::triggered, q, &KMessageWidget::animatedHide); | 94 | QObject::connect(closeAction, &QAction::triggered, q, &KMessageWidget::animatedHide); | ||
102 | 95 | | |||
103 | closeButton = new QToolButton(content); | 96 | closeButton = new QToolButton(q); | ||
104 | closeButton->setAutoRaise(true); | 97 | closeButton->setAutoRaise(true); | ||
105 | closeButton->setDefaultAction(closeAction); | 98 | closeButton->setDefaultAction(closeAction); | ||
106 | 99 | | |||
107 | q->setMessageType(KMessageWidget::Information); | 100 | q->setMessageType(KMessageWidget::Information); | ||
108 | } | 101 | } | ||
109 | 102 | | |||
110 | void KMessageWidgetPrivate::createLayout() | 103 | void KMessageWidgetPrivate::createLayout() | ||
111 | { | 104 | { | ||
112 | delete content->layout(); | 105 | delete q->layout(); | ||
113 | | ||||
114 | content->resize(q->size()); | | |||
115 | 106 | | |||
116 | qDeleteAll(buttons); | 107 | qDeleteAll(buttons); | ||
117 | buttons.clear(); | 108 | buttons.clear(); | ||
118 | 109 | | |||
119 | const auto actions = q->actions(); | 110 | const auto actions = q->actions(); | ||
120 | buttons.reserve(actions.size()); | 111 | buttons.reserve(actions.size()); | ||
121 | for (QAction *action : actions) { | 112 | for (QAction *action : actions) { | ||
122 | QToolButton *button = new QToolButton(content); | 113 | QToolButton *button = new QToolButton(q); | ||
123 | button->setDefaultAction(action); | 114 | button->setDefaultAction(action); | ||
124 | button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); | 115 | button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); | ||
125 | buttons.append(button); | 116 | buttons.append(button); | ||
126 | } | 117 | } | ||
127 | 118 | | |||
128 | // AutoRaise reduces visual clutter, but we don't want to turn it on if | 119 | // AutoRaise reduces visual clutter, but we don't want to turn it on if | ||
129 | // there are other buttons, otherwise the close button will look different | 120 | // there are other buttons, otherwise the close button will look different | ||
130 | // from the others. | 121 | // from the others. | ||
131 | closeButton->setAutoRaise(buttons.isEmpty()); | 122 | closeButton->setAutoRaise(buttons.isEmpty()); | ||
132 | | ||||
133 | if (wordWrap) { | 123 | if (wordWrap) { | ||
134 | QGridLayout *layout = new QGridLayout(content); | 124 | QGridLayout *layout = new QGridLayout(q); | ||
135 | // Set alignment to make sure icon does not move down if text wraps | 125 | // Set alignment to make sure icon does not move down if text wraps | ||
136 | layout->addWidget(iconLabel, 0, 0, 1, 1, Qt::AlignHCenter | Qt::AlignTop); | 126 | layout->addWidget(iconLabel, 0, 0, 1, 1, Qt::AlignHCenter | Qt::AlignTop); | ||
137 | layout->addWidget(textLabel, 0, 1); | 127 | layout->addWidget(textLabel, 0, 1); | ||
138 | 128 | | |||
139 | if (buttons.isEmpty()) { | 129 | if (buttons.isEmpty()) { | ||
140 | // Use top-vertical alignment like the icon does. | 130 | // Use top-vertical alignment like the icon does. | ||
141 | layout->addWidget(closeButton, 0, 2, 1, 1, Qt::AlignHCenter | Qt::AlignTop); | 131 | layout->addWidget(closeButton, 0, 2, 1, 1, Qt::AlignHCenter | Qt::AlignTop); | ||
142 | } else { | 132 | } else { | ||
143 | // Use an additional layout in row 1 for the buttons. | 133 | // Use an additional layout in row 1 for the buttons. | ||
144 | QHBoxLayout *buttonLayout = new QHBoxLayout; | 134 | QHBoxLayout *buttonLayout = new QHBoxLayout; | ||
145 | buttonLayout->addStretch(); | 135 | buttonLayout->addStretch(); | ||
146 | for (QToolButton *button : qAsConst(buttons)) { | 136 | for (QToolButton *button : qAsConst(buttons)) { | ||
147 | // For some reason, calling show() is necessary if wordwrap is true, | 137 | // For some reason, calling show() is necessary if wordwrap is true, | ||
148 | // otherwise the buttons do not show up. It is not needed if | 138 | // otherwise the buttons do not show up. It is not needed if | ||
149 | // wordwrap is false. | 139 | // wordwrap is false. | ||
150 | button->show(); | 140 | button->show(); | ||
151 | buttonLayout->addWidget(button); | 141 | buttonLayout->addWidget(button); | ||
152 | } | 142 | } | ||
153 | buttonLayout->addWidget(closeButton); | 143 | buttonLayout->addWidget(closeButton); | ||
154 | layout->addItem(buttonLayout, 1, 0, 1, 2); | 144 | layout->addItem(buttonLayout, 1, 0, 1, 2); | ||
155 | } | 145 | } | ||
156 | } else { | 146 | } else { | ||
157 | QHBoxLayout *layout = new QHBoxLayout(content); | 147 | QHBoxLayout *layout = new QHBoxLayout(q); | ||
158 | layout->addWidget(iconLabel); | 148 | layout->addWidget(iconLabel); | ||
159 | layout->addWidget(textLabel); | 149 | layout->addWidget(textLabel); | ||
160 | 150 | | |||
161 | for (QToolButton *button : qAsConst(buttons)) { | 151 | for (QToolButton *button : qAsConst(buttons)) { | ||
162 | layout->addWidget(button); | 152 | layout->addWidget(button); | ||
163 | } | 153 | } | ||
164 | | ||||
165 | layout->addWidget(closeButton); | 154 | layout->addWidget(closeButton); | ||
166 | }; | 155 | }; | ||
167 | 156 | // Add bordersize to the margin so it starts from the inner border and doesn't look to cramped | |||
157 | q->layout()->setContentsMargins(q->layout()->contentsMargins() + borderSize); | ||||
cfeck: too | |||||
168 | if (q->isVisible()) { | 158 | if (q->isVisible()) { | ||
169 | q->setFixedHeight(content->sizeHint().height()); | 159 | q->setFixedHeight(q->sizeHint().height()); | ||
170 | } | 160 | } | ||
171 | q->updateGeometry(); | 161 | q->updateGeometry(); | ||
172 | } | 162 | } | ||
173 | 163 | | |||
174 | void KMessageWidgetPrivate::applyStyleSheet() | 164 | void KMessageWidgetPrivate::setPalette() | ||
175 | { | 165 | { | ||
176 | QColor bgBaseColor; | 166 | QColor bgBaseColor; | ||
177 | 167 | | |||
178 | // We have to hardcode colors here because KWidgetsAddons is a tier 1 framework | 168 | // We have to hardcode colors here because KWidgetsAddons is a tier 1 framework | ||
179 | // and therefore can't depend on any other KDE Frameworks | 169 | // and therefore can't depend on any other KDE Frameworks | ||
180 | // The following RGB color values come from the "default" scheme in kcolorscheme.cpp | 170 | // The following RGB color values come from the "default" scheme in kcolorscheme.cpp | ||
181 | switch (messageType) { | 171 | switch (messageType) { | ||
182 | case KMessageWidget::Positive: | 172 | case KMessageWidget::Positive: | ||
183 | bgBaseColor.setRgb(39, 174, 96); // Window: ForegroundPositive | 173 | bgBaseColor.setRgb(39, 174, 96); // Window: ForegroundPositive | ||
184 | break; | 174 | break; | ||
185 | case KMessageWidget::Information: | 175 | case KMessageWidget::Information: | ||
186 | bgBaseColor.setRgb(61, 174, 233); // Window: ForegroundActive | 176 | bgBaseColor.setRgb(61, 174, 233); // Window: ForegroundActive | ||
187 | break; | 177 | break; | ||
188 | case KMessageWidget::Warning: | 178 | case KMessageWidget::Warning: | ||
189 | bgBaseColor.setRgb(246, 116, 0); // Window: ForegroundNeutral | 179 | bgBaseColor.setRgb(246, 116, 0); // Window: ForegroundNeutral | ||
190 | break; | 180 | break; | ||
191 | case KMessageWidget::Error: | 181 | case KMessageWidget::Error: | ||
192 | bgBaseColor.setRgb(218, 68, 83); // Window: ForegroundNegative | 182 | bgBaseColor.setRgb(218, 68, 83); // Window: ForegroundNegative | ||
193 | break; | 183 | break; | ||
194 | } | 184 | } | ||
195 | const qreal bgBaseColorAlpha = 0.2; | 185 | QPalette palette = q->palette(); | ||
196 | bgBaseColor.setAlphaF(bgBaseColorAlpha); | 186 | palette.setColor(QPalette::Window, bgBaseColor); | ||
197 | 187 | q->setPalette(palette); | |||
198 | const QPalette palette = QGuiApplication::palette(); | | |||
199 | const QColor windowColor = palette.window().color(); | | |||
200 | const QColor textColor = palette.text().color(); | | |||
201 | const QColor border = bgBaseColor; | | |||
202 | | ||||
203 | // Generate a final background color from overlaying bgBaseColor over windowColor | | |||
204 | const int newRed = (bgBaseColor.red() * bgBaseColorAlpha) + (windowColor.red() * (1 - bgBaseColorAlpha)); | | |||
205 | const int newGreen = (bgBaseColor.green() * bgBaseColorAlpha) + (windowColor.green() * (1 - bgBaseColorAlpha)); | | |||
206 | const int newBlue = (bgBaseColor.blue() * bgBaseColorAlpha) + (windowColor.blue() * (1 - bgBaseColorAlpha)); | | |||
207 | | ||||
208 | const QColor bgFinalColor = QColor(newRed, newGreen, newBlue); | | |||
209 | | ||||
210 | content->setStyleSheet( | | |||
211 | QString::fromLatin1(".QFrame {" | | |||
212 | "background-color: %1;" | | |||
213 | "border-radius: 4px;" | | |||
214 | "border: 2px solid %2;" | | |||
215 | "margin: %3px;" | | |||
216 | "}" | | |||
217 | ".QLabel { color: %4; }" | | |||
218 | ) | | |||
219 | .arg(bgFinalColor.name()) | | |||
220 | .arg(border.name()) | | |||
221 | // DefaultFrameWidth returns the size of the external margin + border width. We know our border is 2px, so we subtract this from the frame normal QStyle FrameWidth to get our margin | | |||
222 | .arg(q->style()->pixelMetric(QStyle::PM_DefaultFrameWidth, nullptr, q) - 2) | | |||
223 | .arg(textColor.name()) | | |||
224 | ); | | |||
225 | } | 188 | } | ||
226 | 189 | | |||
227 | void KMessageWidgetPrivate::updateLayout() | 190 | void KMessageWidgetPrivate::updateLayout() | ||
228 | { | 191 | { | ||
229 | if (content->layout()) { | | |||
230 | createLayout(); | 192 | createLayout(); | ||
231 | } | 193 | } | ||
232 | } | | |||
233 | | ||||
234 | void KMessageWidgetPrivate::updateSnapShot() | | |||
235 | { | | |||
236 | // Attention: updateSnapShot calls QWidget::render(), which causes the whole | | |||
237 | // window layouts to be activated. Calling this method from resizeEvent() | | |||
238 | // can lead to infinite recursion, see: | | |||
239 | // https://bugs.kde.org/show_bug.cgi?id=311336 | | |||
240 | contentSnapShot = QPixmap(content->size() * q->devicePixelRatioF()); | | |||
241 | contentSnapShot.setDevicePixelRatio(q->devicePixelRatioF()); | | |||
242 | contentSnapShot.fill(Qt::transparent); | | |||
243 | content->render(&contentSnapShot, QPoint(), QRegion(), QWidget::DrawChildren); | | |||
244 | } | | |||
245 | 194 | | |||
cfeck: typo: it is | |||||
246 | void KMessageWidgetPrivate::slotTimeLineChanged(qreal value) | 195 | void KMessageWidgetPrivate::slotTimeLineChanged(qreal value) | ||
247 | { | 196 | { | ||
248 | q->setFixedHeight(qMin(value * 2, qreal(1.0)) * content->height()); | 197 | q->setFixedHeight(qMin(value * 2, qreal(1.0)) * bestContentHeight()); | ||
249 | q->update(); | 198 | q->update(); | ||
250 | } | 199 | } | ||
251 | 200 | | |||
252 | void KMessageWidgetPrivate::slotTimeLineFinished() | 201 | void KMessageWidgetPrivate::slotTimeLineFinished() | ||
253 | { | 202 | { | ||
254 | if (timeLine->direction() == QTimeLine::Forward) { | 203 | if (timeLine->direction() == QTimeLine::Forward) { | ||
255 | // Show | 204 | q->resize(q->width(), bestContentHeight()); | ||
256 | // We set the whole geometry here, because it may be wrong if a | | |||
257 | // KMessageWidget is shown right when the toplevel window is created. | | |||
258 | content->setGeometry(0, 0, q->width(), bestContentHeight()); | | |||
259 | 205 | | |||
260 | // notify about finished animation | 206 | // notify about finished animation | ||
261 | emit q->showAnimationFinished(); | 207 | emit q->showAnimationFinished(); | ||
262 | } else { | 208 | } else { | ||
263 | // hide and notify about finished animation | 209 | // hide and notify about finished animation | ||
264 | q->hide(); | 210 | q->hide(); | ||
265 | emit q->hideAnimationFinished(); | 211 | emit q->hideAnimationFinished(); | ||
266 | } | 212 | } | ||
267 | } | 213 | } | ||
268 | 214 | | |||
269 | int KMessageWidgetPrivate::bestContentHeight() const | 215 | int KMessageWidgetPrivate::bestContentHeight() const | ||
270 | { | 216 | { | ||
271 | int height = content->heightForWidth(q->width()); | 217 | int height = q->heightForWidth(q->width()); | ||
272 | if (height == -1) { | 218 | if (height == -1) { | ||
273 | height = content->sizeHint().height(); | 219 | height = q->sizeHint().height(); | ||
274 | } | 220 | } | ||
275 | return height; | 221 | return height; | ||
276 | } | 222 | } | ||
277 | 223 | | |||
278 | //--------------------------------------------------------------------- | 224 | //--------------------------------------------------------------------- | ||
279 | // KMessageWidget | 225 | // KMessageWidget | ||
280 | //--------------------------------------------------------------------- | 226 | //--------------------------------------------------------------------- | ||
281 | KMessageWidget::KMessageWidget(QWidget *parent) | 227 | KMessageWidget::KMessageWidget(QWidget *parent) | ||
Show All 30 Lines | |||||
312 | KMessageWidget::MessageType KMessageWidget::messageType() const | 258 | KMessageWidget::MessageType KMessageWidget::messageType() const | ||
313 | { | 259 | { | ||
314 | return d->messageType; | 260 | return d->messageType; | ||
315 | } | 261 | } | ||
316 | 262 | | |||
317 | void KMessageWidget::setMessageType(KMessageWidget::MessageType type) | 263 | void KMessageWidget::setMessageType(KMessageWidget::MessageType type) | ||
318 | { | 264 | { | ||
319 | d->messageType = type; | 265 | d->messageType = type; | ||
320 | d->applyStyleSheet(); | 266 | d->setPalette(); | ||
321 | } | 267 | } | ||
322 | 268 | | |||
323 | QSize KMessageWidget::sizeHint() const | 269 | QSize KMessageWidget::sizeHint() const | ||
324 | { | 270 | { | ||
325 | ensurePolished(); | 271 | ensurePolished(); | ||
326 | return d->content->sizeHint(); | 272 | return QFrame::sizeHint(); | ||
327 | } | 273 | } | ||
328 | 274 | | |||
329 | QSize KMessageWidget::minimumSizeHint() const | 275 | QSize KMessageWidget::minimumSizeHint() const | ||
330 | { | 276 | { | ||
331 | ensurePolished(); | 277 | ensurePolished(); | ||
332 | return d->content->minimumSizeHint(); | 278 | return QFrame::minimumSizeHint(); | ||
333 | } | 279 | } | ||
334 | 280 | | |||
335 | bool KMessageWidget::event(QEvent *event) | 281 | bool KMessageWidget::event(QEvent *event) | ||
336 | { | 282 | { | ||
337 | if (event->type() == QEvent::Polish && !d->content->layout()) { | 283 | if (event->type() == QEvent::Polish && !layout()) { | ||
338 | d->createLayout(); | 284 | d->createLayout(); | ||
339 | } else if (event->type() == QEvent::PaletteChange) { | 285 | } else if (event->type() == QEvent::PaletteChange) { | ||
340 | d->applyStyleSheet(); | 286 | d->setPalette(); | ||
341 | } else if (event->type() == QEvent::Show && !d->ignoreShowEventDoingAnimatedShow) { | 287 | } else if (event->type() == QEvent::Show && !d->ignoreShowEventDoingAnimatedShow) { | ||
342 | if ((height() != d->content->height()) || (d->content->pos().y() != 0)) { | 288 | setFixedHeight(d->bestContentHeight()); | ||
343 | d->content->move(0, 0); | | |||
344 | setFixedHeight(d->content->height()); | | |||
345 | } | | |||
346 | } | 289 | } | ||
347 | return QFrame::event(event); | 290 | return QFrame::event(event); | ||
348 | } | 291 | } | ||
349 | 292 | | |||
350 | void KMessageWidget::resizeEvent(QResizeEvent *event) | 293 | void KMessageWidget::resizeEvent(QResizeEvent *event) | ||
351 | { | 294 | { | ||
352 | QFrame::resizeEvent(event); | 295 | QFrame::resizeEvent(event); | ||
353 | | ||||
354 | if (d->timeLine->state() == QTimeLine::NotRunning) { | 296 | if (d->timeLine->state() == QTimeLine::NotRunning) { | ||
355 | d->content->resize(width(), d->bestContentHeight()); | 297 | setFixedHeight(d->bestContentHeight()); | ||
356 | } | 298 | } | ||
357 | } | 299 | } | ||
358 | 300 | | |||
359 | int KMessageWidget::heightForWidth(int width) const | 301 | int KMessageWidget::heightForWidth(int width) const | ||
360 | { | 302 | { | ||
361 | ensurePolished(); | 303 | ensurePolished(); | ||
362 | return d->content->heightForWidth(width); | 304 | return QFrame::heightForWidth(width); | ||
363 | } | 305 | } | ||
364 | | ||||
365 | void KMessageWidget::paintEvent(QPaintEvent *event) | 306 | void KMessageWidget::paintEvent(QPaintEvent *event) | ||
366 | { | 307 | { | ||
367 | QFrame::paintEvent(event); | 308 | Q_UNUSED(event) | ||
368 | if (d->timeLine->state() == QTimeLine::Running) { | | |||
369 | QPainter painter(this); | 309 | QPainter painter(this); | ||
310 | if (d->timeLine->state() == QTimeLine::Running) { | ||||
370 | painter.setOpacity(d->timeLine->currentValue() * d->timeLine->currentValue()); | 311 | painter.setOpacity(d->timeLine->currentValue() * d->timeLine->currentValue()); | ||
371 | painter.drawPixmap(0, 0, d->contentSnapShot); | | |||
372 | } | 312 | } | ||
313 | constexpr float radius = 4 * 0.6; | ||||
314 | const QRect innerRect = rect().marginsRemoved(QMargins() + borderSize/2); | ||||
cfeck: missing spaces around `/` | |||||
315 | const QColor color = palette().color(QPalette::Window); | ||||
316 | constexpr float alpha = 0.2; | ||||
317 | const auto parentWidget = qobject_cast<QWidget*>(parent()); | ||||
Can't you use parentWidget()? dhaumann: Can't you use parentWidget()?
See: https://doc.qt.io/qt-5/qwidget.html#parentWidget | |||||
I knew there was a function like that but couldn't remember its name. Thanks! davidre: I knew there was a function like that but couldn't remember its name. Thanks! | |||||
318 | const QColor parentWindowColor = (parentWidget ? parentWidget->palette() : qApp->palette()).color(QPalette::Window); | ||||
319 | const int newRed = (color.red() * alpha) + (parentWindowColor.red() * (1 - alpha)); | ||||
320 | const int newGreen = (color.green() * alpha) + (parentWindowColor.green() * (1 - alpha)); | ||||
321 | const int newBlue = (color.blue() * alpha) + (parentWindowColor.blue() * (1 - alpha)); | ||||
322 | painter.setPen(QPen(color, borderSize)); | ||||
323 | painter.setBrush(QColor(newRed, newGreen, newBlue)); | ||||
324 | painter.setRenderHint(QPainter::Antialiasing); | ||||
325 | painter.drawRoundedRect(innerRect, radius, radius); | ||||
373 | } | 326 | } | ||
374 | 327 | | |||
375 | bool KMessageWidget::wordWrap() const | 328 | bool KMessageWidget::wordWrap() const | ||
376 | { | 329 | { | ||
377 | return d->wordWrap; | 330 | return d->wordWrap; | ||
378 | } | 331 | } | ||
379 | 332 | | |||
380 | void KMessageWidget::setWordWrap(bool wordWrap) | 333 | void KMessageWidget::setWordWrap(bool wordWrap) | ||
▲ Show 20 Lines • Show All 45 Lines • ▼ Show 20 Line(s) | 373 | { | |||
426 | 379 | | |||
427 | if (!style()->styleHint(QStyle::SH_Widget_Animate, nullptr, this) | 380 | if (!style()->styleHint(QStyle::SH_Widget_Animate, nullptr, this) | ||
428 | || (parentWidget() && !parentWidget()->isVisible())) { | 381 | || (parentWidget() && !parentWidget()->isVisible())) { | ||
429 | show(); | 382 | show(); | ||
430 | emit showAnimationFinished(); | 383 | emit showAnimationFinished(); | ||
431 | return; | 384 | return; | ||
432 | } | 385 | } | ||
433 | 386 | | |||
434 | if (isVisible() && (d->timeLine->state() == QTimeLine::NotRunning) && (height() == d->bestContentHeight()) && (d->content->pos().y() == 0)) { | 387 | if (isVisible() && (d->timeLine->state() == QTimeLine::NotRunning) && (height() == d->bestContentHeight())){ | ||
cfeck: missing space before `{` | |||||
435 | emit showAnimationFinished(); | 388 | emit showAnimationFinished(); | ||
436 | return; | 389 | return; | ||
437 | } | 390 | } | ||
438 | 391 | | |||
439 | d->ignoreShowEventDoingAnimatedShow = true; | 392 | d->ignoreShowEventDoingAnimatedShow = true; | ||
440 | show(); | 393 | show(); | ||
441 | d->ignoreShowEventDoingAnimatedShow = false; | 394 | d->ignoreShowEventDoingAnimatedShow = false; | ||
442 | setFixedHeight(0); | 395 | setFixedHeight(0); | ||
443 | int wantedHeight = d->bestContentHeight(); | | |||
444 | d->content->setGeometry(0, -wantedHeight, width(), wantedHeight); | | |||
445 | | ||||
446 | d->updateSnapShot(); | | |||
447 | 396 | | |||
448 | d->timeLine->setDirection(QTimeLine::Forward); | 397 | d->timeLine->setDirection(QTimeLine::Forward); | ||
449 | if (d->timeLine->state() == QTimeLine::NotRunning) { | 398 | if (d->timeLine->state() == QTimeLine::NotRunning) { | ||
450 | d->timeLine->start(); | 399 | d->timeLine->start(); | ||
451 | } | 400 | } | ||
452 | } | 401 | } | ||
453 | 402 | | |||
454 | void KMessageWidget::animatedHide() | 403 | void KMessageWidget::animatedHide() | ||
Show All 14 Lines | 404 | { | |||
469 | 418 | | |||
470 | if (!isVisible()) { | 419 | if (!isVisible()) { | ||
471 | // explicitly hide it, so it stays hidden in case it is only not visible due to the parents | 420 | // explicitly hide it, so it stays hidden in case it is only not visible due to the parents | ||
472 | hide(); | 421 | hide(); | ||
473 | emit hideAnimationFinished(); | 422 | emit hideAnimationFinished(); | ||
474 | return; | 423 | return; | ||
475 | } | 424 | } | ||
476 | 425 | | |||
477 | d->content->move(0, -d->content->height()); | | |||
478 | d->updateSnapShot(); | | |||
479 | | ||||
480 | d->timeLine->setDirection(QTimeLine::Backward); | 426 | d->timeLine->setDirection(QTimeLine::Backward); | ||
481 | if (d->timeLine->state() == QTimeLine::NotRunning) { | 427 | if (d->timeLine->state() == QTimeLine::NotRunning) { | ||
482 | d->timeLine->start(); | 428 | d->timeLine->start(); | ||
483 | } | 429 | } | ||
484 | } | 430 | } | ||
485 | 431 | | |||
486 | bool KMessageWidget::isHideAnimationRunning() const | 432 | bool KMessageWidget::isHideAnimationRunning() const | ||
487 | { | 433 | { | ||
Show All 29 Lines |
Does it need to be static to avoid an external symbol?