• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.8.5 API Reference
  • KDE Home
  • Contact Us
 

KDEUI

  • kdeui
  • widgets
kmessagewidget.cpp
Go to the documentation of this file.
1 /* This file is part of the KDE libraries
2  *
3  * Copyright (c) 2011 Aurélien Gâteau <agateau@kde.org>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18  * 02110-1301 USA
19  */
20 #include "kmessagewidget.h"
21 
22 #include <kaction.h>
23 #include <kcolorscheme.h>
24 #include <kdebug.h>
25 #include <kglobalsettings.h>
26 #include <kicon.h>
27 #include <kiconloader.h>
28 #include <kstandardaction.h>
29 
30 #include <QEvent>
31 #include <QGridLayout>
32 #include <QHBoxLayout>
33 #include <QLabel>
34 #include <QPainter>
35 #include <QShowEvent>
36 #include <QTimeLine>
37 #include <QToolButton>
38 
39 //---------------------------------------------------------------------
40 // KMessageWidgetPrivate
41 //---------------------------------------------------------------------
42 class KMessageWidgetPrivate
43 {
44 public:
45  void init(KMessageWidget*);
46 
47  KMessageWidget* q;
48  QFrame* content;
49  QLabel* iconLabel;
50  QLabel* textLabel;
51  QToolButton* closeButton;
52  QTimeLine* timeLine;
53 
54  KMessageWidget::MessageType messageType;
55  bool wordWrap;
56  QList<QToolButton*> buttons;
57  QPixmap contentSnapShot;
58 
59  void createLayout();
60  void updateSnapShot();
61  void updateLayout();
62  void slotTimeLineChanged(qreal);
63  void slotTimeLineFinished();
64 };
65 
66 void KMessageWidgetPrivate::init(KMessageWidget *q_ptr)
67 {
68  q = q_ptr;
69 
70  q->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
71 
72  timeLine = new QTimeLine(500, q);
73  QObject::connect(timeLine, SIGNAL(valueChanged(qreal)), q, SLOT(slotTimeLineChanged(qreal)));
74  QObject::connect(timeLine, SIGNAL(finished()), q, SLOT(slotTimeLineFinished()));
75 
76  content = new QFrame(q);
77  content->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
78 
79  wordWrap = false;
80 
81  iconLabel = new QLabel(content);
82  iconLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
83 
84  textLabel = new QLabel(content);
85  textLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
86  textLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
87 
88  KAction* closeAction = KStandardAction::close(q, SLOT(animatedHide()), q);
89 
90  closeButton = new QToolButton(content);
91  closeButton->setAutoRaise(true);
92  closeButton->setDefaultAction(closeAction);
93 
94  q->setMessageType(KMessageWidget::Information);
95 }
96 
97 void KMessageWidgetPrivate::createLayout()
98 {
99  delete content->layout();
100 
101  content->resize(q->size());
102 
103  qDeleteAll(buttons);
104  buttons.clear();
105 
106  Q_FOREACH(QAction* action, q->actions()) {
107  QToolButton* button = new QToolButton(content);
108  button->setDefaultAction(action);
109  button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
110  buttons.append(button);
111  }
112 
113  // AutoRaise reduces visual clutter, but we don't want to turn it on if
114  // there are other buttons, otherwise the close button will look different
115  // from the others.
116  closeButton->setAutoRaise(buttons.isEmpty());
117 
118  if (wordWrap) {
119  QGridLayout* layout = new QGridLayout(content);
120  // Set alignment to make sure icon does not move down if text wraps
121  layout->addWidget(iconLabel, 0, 0, 1, 1, Qt::AlignHCenter | Qt::AlignTop);
122  layout->addWidget(textLabel, 0, 1);
123 
124  QHBoxLayout* buttonLayout = new QHBoxLayout;
125  buttonLayout->addStretch();
126  Q_FOREACH(QToolButton* button, buttons) {
127  // For some reason, calling show() is necessary if wordwrap is true,
128  // otherwise the buttons do not show up. It is not needed if
129  // wordwrap is false.
130  button->show();
131  buttonLayout->addWidget(button);
132  }
133  buttonLayout->addWidget(closeButton);
134  layout->addItem(buttonLayout, 1, 0, 1, 2);
135  } else {
136  QHBoxLayout* layout = new QHBoxLayout(content);
137  layout->addWidget(iconLabel);
138  layout->addWidget(textLabel);
139 
140  Q_FOREACH(QToolButton* button, buttons) {
141  layout->addWidget(button);
142  }
143 
144  layout->addWidget(closeButton);
145  };
146 
147  if (q->isVisible()) {
148  q->setFixedHeight(content->sizeHint().height());
149  }
150  q->updateGeometry();
151 }
152 
153 void KMessageWidgetPrivate::updateLayout()
154 {
155  if (content->layout()) {
156  createLayout();
157  }
158 }
159 
160 void KMessageWidgetPrivate::updateSnapShot()
161 {
162  contentSnapShot = QPixmap(content->size());
163  contentSnapShot.fill(Qt::transparent);
164  content->render(&contentSnapShot, QPoint(), QRegion(), QWidget::DrawChildren);
165 }
166 
167 void KMessageWidgetPrivate::slotTimeLineChanged(qreal value)
168 {
169  q->setFixedHeight(qMin(value * 2, qreal(1.0)) * content->height());
170  q->update();
171 }
172 
173 void KMessageWidgetPrivate::slotTimeLineFinished()
174 {
175  if (timeLine->direction() == QTimeLine::Forward) {
176  // Show
177  content->move(0, 0);
178  } else {
179  // Hide
180  q->hide();
181  }
182 }
183 
184 
185 //---------------------------------------------------------------------
186 // KMessageWidget
187 //---------------------------------------------------------------------
188 KMessageWidget::KMessageWidget(QWidget* parent)
189  : QFrame(parent)
190  , d(new KMessageWidgetPrivate)
191 {
192  d->init(this);
193 }
194 
195 KMessageWidget::KMessageWidget(const QString& text, QWidget* parent)
196  : QFrame(parent)
197  , d(new KMessageWidgetPrivate)
198 {
199  d->init(this);
200  setText(text);
201 }
202 
203 KMessageWidget::~KMessageWidget()
204 {
205  delete d;
206 }
207 
208 QString KMessageWidget::text() const
209 {
210  return d->textLabel->text();
211 }
212 
213 void KMessageWidget::setText(const QString& text)
214 {
215  d->textLabel->setText(text);
216  updateGeometry();
217 }
218 
219 KMessageWidget::MessageType KMessageWidget::messageType() const
220 {
221  return d->messageType;
222 }
223 
224 static void getColorsFromColorScheme(KColorScheme::BackgroundRole bgRole, QColor* bg, QColor* fg)
225 {
226  KColorScheme scheme(QPalette::Active, KColorScheme::Window);
227  *bg = scheme.background(bgRole).color();
228  *fg = scheme.foreground().color();
229 }
230 
231 void KMessageWidget::setMessageType(KMessageWidget::MessageType type)
232 {
233  d->messageType = type;
234  KIcon icon;
235  QColor bg0, bg1, bg2, border, fg;
236  switch (type) {
237  case Positive:
238  icon = KIcon("dialog-ok");
239  getColorsFromColorScheme(KColorScheme::PositiveBackground, &bg1, &fg);
240  break;
241  case Information:
242  icon = KIcon("dialog-information");
243  // There is no "information" background role in KColorScheme, use the
244  // colors of highlighted items instead
245  bg1 = palette().highlight().color();
246  fg = palette().highlightedText().color();
247  break;
248  case Warning:
249  icon = KIcon("dialog-warning");
250  getColorsFromColorScheme(KColorScheme::NeutralBackground, &bg1, &fg);
251  break;
252  case Error:
253  icon = KIcon("dialog-error");
254  getColorsFromColorScheme(KColorScheme::NegativeBackground, &bg1, &fg);
255  break;
256  }
257 
258  // Colors
259  bg0 = bg1.lighter(110);
260  bg2 = bg1.darker(110);
261  border = KColorScheme::shade(bg1, KColorScheme::DarkShade);
262 
263  d->content->setStyleSheet(
264  QString(".QFrame {"
265  "background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,"
266  " stop: 0 %1,"
267  " stop: 0.1 %2,"
268  " stop: 1.0 %3);"
269  "border-radius: 5px;"
270  "border: 1px solid %4;"
271  "}"
272  ".QLabel { color: %5; }"
273  )
274  .arg(bg0.name())
275  .arg(bg1.name())
276  .arg(bg2.name())
277  .arg(border.name())
278  .arg(fg.name())
279  );
280 
281  // Icon
282  const int size = KIconLoader::global()->currentSize(KIconLoader::MainToolbar);
283  d->iconLabel->setPixmap(icon.pixmap(size));
284 }
285 
286 QSize KMessageWidget::sizeHint() const
287 {
288  ensurePolished();
289  return d->content->sizeHint();
290 }
291 
292 QSize KMessageWidget::minimumSizeHint() const
293 {
294  ensurePolished();
295  return d->content->minimumSizeHint();
296 }
297 
298 bool KMessageWidget::event(QEvent* event)
299 {
300  if (event->type() == QEvent::Polish && !d->content->layout()) {
301  d->createLayout();
302  }
303  return QFrame::event(event);
304 }
305 
306 void KMessageWidget::resizeEvent(QResizeEvent* event)
307 {
308  QFrame::resizeEvent(event);
309  if (d->timeLine->state() == QTimeLine::NotRunning) {
310  int contentHeight = d->content->heightForWidth(width());
311  if (contentHeight == -1) {
312  contentHeight = d->content->sizeHint().height();
313  }
314  d->content->resize(width(), contentHeight);
315  }
316 }
317 
318 int KMessageWidget::heightForWidth(int width) const
319 {
320  ensurePolished();
321  return d->content->heightForWidth(width);
322 }
323 
324 void KMessageWidget::paintEvent(QPaintEvent* event)
325 {
326  QFrame::paintEvent(event);
327  if (d->timeLine->state() == QTimeLine::Running) {
328  QPainter painter(this);
329  painter.setOpacity(d->timeLine->currentValue() * d->timeLine->currentValue());
330  painter.drawPixmap(0, 0, d->contentSnapShot);
331  }
332 }
333 
334 void KMessageWidget::showEvent(QShowEvent* event)
335 {
336  // Keep this method here to avoid breaking binary compatibility:
337  // QFrame::showEvent() used to be reimplemented.
338  QFrame::showEvent(event);
339 }
340 
341 bool KMessageWidget::wordWrap() const
342 {
343  return d->wordWrap;
344 }
345 
346 void KMessageWidget::setWordWrap(bool wordWrap)
347 {
348  d->wordWrap = wordWrap;
349  d->textLabel->setWordWrap(wordWrap);
350  d->updateLayout();
351 }
352 
353 bool KMessageWidget::isCloseButtonVisible() const
354 {
355  return d->closeButton->isVisible();
356 }
357 
358 void KMessageWidget::setCloseButtonVisible(bool show)
359 {
360  d->closeButton->setVisible(show);
361 }
362 
363 void KMessageWidget::addAction(QAction* action)
364 {
365  QFrame::addAction(action);
366  d->updateLayout();
367 }
368 
369 void KMessageWidget::removeAction(QAction* action)
370 {
371  QFrame::removeAction(action);
372  d->updateLayout();
373 }
374 
375 void KMessageWidget::animatedShow()
376 {
377  if (!(KGlobalSettings::graphicEffectsLevel() & KGlobalSettings::SimpleAnimationEffects)) {
378  show();
379  return;
380  }
381 
382  if (isVisible()) {
383  return;
384  }
385 
386  QFrame::show();
387  setFixedHeight(0);
388  int wantedHeight = d->content->sizeHint().height();
389  d->content->setGeometry(0, -wantedHeight, width(), wantedHeight);
390 
391  d->updateSnapShot();
392 
393  d->timeLine->setDirection(QTimeLine::Forward);
394  if (d->timeLine->state() == QTimeLine::NotRunning) {
395  d->timeLine->start();
396  }
397 }
398 
399 void KMessageWidget::animatedHide()
400 {
401  if (!(KGlobalSettings::graphicEffectsLevel() & KGlobalSettings::SimpleAnimationEffects)) {
402  hide();
403  return;
404  }
405 
406  if (!isVisible()) {
407  return;
408  }
409 
410  d->content->move(0, -d->content->height());
411  d->updateSnapShot();
412 
413  d->timeLine->setDirection(QTimeLine::Backward);
414  if (d->timeLine->state() == QTimeLine::NotRunning) {
415  d->timeLine->start();
416  }
417 }
418 
419 #include "kmessagewidget.moc"
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Fri Dec 7 2012 16:04:41 by doxygen 1.8.1 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KDEUI

Skip menu "KDEUI"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Modules
  • Related Pages

kdelibs-4.8.5 API Reference

Skip menu "kdelibs-4.8.5 API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal