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