• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • applications API Reference
  • KDE Home
  • Contact Us
 

libkonq

  • sources
  • kde-4.12
  • applications
  • kde-baseapps
  • lib
  • konq
konq_statusbarmessagelabel.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * Copyright (C) 2006 by Peter Penz *
3  * peter.penz@gmx.at *
4  * *
5  * This program is free software; you can redistribute it and/or modify *
6  * it under the terms of the GNU General Public License as published by *
7  * the Free Software Foundation; either version 2 of the License, or *
8  * (at your option) any later version. *
9  * *
10  * This program 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 *
13  * GNU General Public License for more details. *
14  * *
15  * You should have received a copy of the GNU General Public License *
16  * along with this program; if not, write to the *
17  * Free Software Foundation, Inc., *
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
19  ***************************************************************************/
20 
21 #include "konq_statusbarmessagelabel.h"
22 #include <QStyle>
23 #include <QTextDocument>
24 
25 #include <kcolorscheme.h>
26 #include <kiconloader.h>
27 #include <kicon.h>
28 #include <klocale.h>
29 #include <kdebug.h>
30 
31 #include <QFontMetrics>
32 #include <QPainter>
33 #include <QKeyEvent>
34 #include <QPixmap>
35 #include <QToolButton>
36 #include <QTimer>
37 
38 enum { GeometryTimeout = 100 };
39 enum { BorderGap = 2 };
40 
41 class KonqStatusBarMessageLabel::Private
42 {
43 public:
44  Private() :
45  m_type(Default),
46  m_state(DefaultState),
47  m_illumination(0),
48  m_minTextHeight(-1),
49  m_timer(0),
50  m_closeButton(0)
51  {}
52 
53  bool isRichText() const { return m_text.startsWith("<html>") || m_text.startsWith("<qt>"); }
54 
55  KonqStatusBarMessageLabel::Type m_type;
56  KonqStatusBarMessageLabel::State m_state;
57  int m_illumination;
58  int m_minTextHeight;
59  QTimer* m_timer;
60  QString m_text;
61  QString m_defaultText;
62  QTextDocument m_textDocument;
63  QList<QString> m_pendingMessages;
64  QPixmap m_pixmap;
65  QToolButton* m_closeButton;
66 };
67 
68 KonqStatusBarMessageLabel::KonqStatusBarMessageLabel(QWidget* parent) :
69  QWidget(parent), d(new Private)
70 {
71  setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum /*the sizeHint is the max*/);
72 
73  d->m_timer = new QTimer(this);
74  connect(d->m_timer, SIGNAL(timeout()),
75  this, SLOT(timerDone()));
76 
77  d->m_closeButton = new QToolButton(this);
78  d->m_closeButton->setAutoRaise(true);
79  d->m_closeButton->setIcon(KIcon("dialog-close"));
80  d->m_closeButton->setToolTip(i18nc("@info", "Close"));
81  d->m_closeButton->setAccessibleName(i18n("Close"));
82  d->m_closeButton->hide();
83  connect(d->m_closeButton, SIGNAL(clicked()),
84  this, SLOT(closeErrorMessage()));
85 }
86 
87 KonqStatusBarMessageLabel::~KonqStatusBarMessageLabel()
88 {
89  delete d;
90 }
91 
92 void KonqStatusBarMessageLabel::setMessage(const QString& text,
93  Type type)
94 {
95  if ((text == d->m_text) && (type == d->m_type)) {
96  return;
97  }
98 
99  if (d->m_type == Error) {
100  if (type == Error) {
101  d->m_pendingMessages.insert(0, d->m_text);
102  } else if ((d->m_state != DefaultState) || !d->m_pendingMessages.isEmpty()) {
103  // a non-error message should not be shown, as there
104  // are other pending error messages in the queue
105  return;
106  }
107  }
108 
109  d->m_text = text;
110  d->m_type = type;
111 
112  if (d->isRichText()) {
113  d->m_textDocument.setTextWidth(-1);
114  d->m_textDocument.setDefaultFont(font());
115  QString html = "<html><font color=\"";
116  html += palette().windowText().color().name();
117  html += "\">";
118  html += d->m_text;
119  d->m_textDocument.setHtml(html);
120  }
121 
122  d->m_timer->stop();
123  d->m_illumination = 0;
124  d->m_state = DefaultState;
125 
126  const char* iconName = 0;
127  QPixmap pixmap;
128  switch (type) {
129  case OperationCompleted:
130  iconName = "dialog-ok";
131  // "ok" icon should probably be "dialog-success", but we don't have that icon in KDE 4.0
132  d->m_closeButton->hide();
133  break;
134 
135  case Information:
136  iconName = "dialog-information";
137  d->m_closeButton->hide();
138  break;
139 
140  case Error:
141  d->m_timer->start(100);
142  d->m_state = Illuminate;
143 
144  updateCloseButtonPosition();
145  d->m_closeButton->show();
146  updateGeometry();
147  break;
148 
149  case Default:
150  default:
151  d->m_closeButton->hide();
152  updateGeometry();
153  break;
154  }
155 
156  d->m_pixmap = (iconName == 0) ? QPixmap() : SmallIcon(iconName);
157  QTimer::singleShot(GeometryTimeout, this, SLOT(assureVisibleText()));
158 
159  if (type == Error) {
160  setAccessibleName(i18n("Error: %1", text));
161  } else {
162  setAccessibleName(text);
163  }
164 
165  update();
166 }
167 
168 KonqStatusBarMessageLabel::Type KonqStatusBarMessageLabel::type() const
169 {
170  return d->m_type;
171 }
172 
173 QString KonqStatusBarMessageLabel::text() const
174 {
175  return d->m_text;
176 }
177 
178 void KonqStatusBarMessageLabel::setDefaultText(const QString& text)
179 {
180  d->m_defaultText = text;
181 }
182 
183 QString KonqStatusBarMessageLabel::defaultText() const
184 {
185  return d->m_defaultText;
186 }
187 
188 void KonqStatusBarMessageLabel::setMinimumTextHeight(int min)
189 {
190  if (min != d->m_minTextHeight) {
191  d->m_minTextHeight = min;
192  setMinimumHeight(min);
193  if (d->m_closeButton->height() > min) {
194  d->m_closeButton->setFixedHeight(min);
195  }
196  }
197 }
198 
199 int KonqStatusBarMessageLabel::minimumTextHeight() const
200 {
201  return d->m_minTextHeight;
202 }
203 
204 void KonqStatusBarMessageLabel::paintEvent(QPaintEvent* /* event */)
205 {
206  QPainter painter(this);
207 
208  if (d->m_illumination > 0) {
209  // at this point, a: we are a second label being drawn over the already
210  // painted status area, so we can be translucent, and b: our palette's
211  // window color (bg only) seems to be wrong (always black)
212  KColorScheme scheme(palette().currentColorGroup(), KColorScheme::Window);
213  QColor backgroundColor = scheme.background(KColorScheme::NegativeBackground).color();
214  backgroundColor.setAlpha(qMin(255, d->m_illumination * 2));
215  painter.setBrush(backgroundColor);
216  painter.setPen(Qt::NoPen);
217  painter.drawRect(QRect(0, 0, width(), height()));
218  }
219 
220  // draw pixmap
221  int x = BorderGap;
222  const int y = (d->m_minTextHeight - d->m_pixmap.height()) / 2;
223 
224  if (!d->m_pixmap.isNull()) {
225  painter.drawPixmap(x, y, d->m_pixmap);
226  x += d->m_pixmap.width() + BorderGap;
227  }
228 
229  // draw text
230 
231  const QRect availTextRect(x, 0, availableTextWidth(), height());
232 
233  if (d->isRichText()) {
234  const QSize sz = d->m_textDocument.size().toSize();
235 
236  // Vertical centering
237  const QRect textRect = QStyle::alignedRect(Qt::LeftToRight, Qt::AlignLeft | Qt::AlignVCenter, sz, availTextRect);
238  //kDebug() << d->m_text << " sz=" << sz << textRect;
239 
240  // What about wordwrap here?
241 
242  painter.translate(textRect.left(), textRect.top());
243  d->m_textDocument.drawContents(&painter);
244  } else {
245  // plain text
246  painter.setPen(palette().windowText().color());
247  int flags = Qt::AlignVCenter;
248  if (height() > d->m_minTextHeight) {
249  flags = flags | Qt::TextWordWrap;
250  }
251  painter.drawText(availTextRect, flags, d->m_text);
252  }
253  painter.end();
254 }
255 
256 void KonqStatusBarMessageLabel::resizeEvent(QResizeEvent* event)
257 {
258  QWidget::resizeEvent(event);
259  updateCloseButtonPosition();
260  QTimer::singleShot(GeometryTimeout, this, SLOT(assureVisibleText()));
261 }
262 
263 void KonqStatusBarMessageLabel::timerDone()
264 {
265  switch (d->m_state) {
266  case Illuminate: {
267  // increase the illumination
268  const int illumination_max = 128;
269  if (d->m_illumination < illumination_max) {
270  d->m_illumination += 32;
271  if (d->m_illumination > illumination_max) {
272  d->m_illumination = illumination_max;
273  }
274  update();
275  } else {
276  d->m_state = Illuminated;
277  d->m_timer->start(5000);
278  }
279  break;
280  }
281 
282  case Illuminated: {
283  // start desaturation
284  d->m_state = Desaturate;
285  d->m_timer->start(100);
286  break;
287  }
288 
289  case Desaturate: {
290  // desaturate
291  if (d->m_illumination > 0) {
292  d->m_illumination -= 5;
293  update();
294  } else {
295  d->m_state = DefaultState;
296  d->m_timer->stop();
297  }
298  break;
299  }
300 
301  default:
302  break;
303  }
304 }
305 
306 void KonqStatusBarMessageLabel::assureVisibleText()
307 {
308  if (d->m_text.isEmpty()) {
309  return;
310  }
311 
312  int requiredHeight = d->m_minTextHeight;
313  if (d->m_type != Default) {
314  // Calculate the required height of the widget thats
315  // needed for having a fully visible text. Note that for the default
316  // statusbar type (e. g. hover information) increasing the text height
317  // is not wanted, as this might rearrange the layout of items.
318 
319  QFontMetrics fontMetrics(font());
320  const QRect bounds(fontMetrics.boundingRect(0, 0, availableTextWidth(), height(),
321  Qt::AlignVCenter | Qt::TextWordWrap, d->m_text));
322  requiredHeight = bounds.height();
323  if (requiredHeight < d->m_minTextHeight) {
324  requiredHeight = d->m_minTextHeight;
325  }
326  }
327 
328  // Increase/decrease the current height of the widget to the
329  // required height. The increasing/decreasing is done in several
330  // steps to have an animation if the height is modified
331  // (see KonqStatusBarMessageLabel::resizeEvent())
332  const int gap = d->m_minTextHeight / 2;
333  int minHeight = minimumHeight();
334  if (minHeight < requiredHeight) {
335  minHeight += gap;
336  if (minHeight > requiredHeight) {
337  minHeight = requiredHeight;
338  }
339  setMinimumHeight(minHeight);
340  updateGeometry();
341  } else if (minHeight > requiredHeight) {
342  minHeight -= gap;
343  if (minHeight < requiredHeight) {
344  minHeight = requiredHeight;
345  }
346  setMinimumHeight(minHeight);
347  updateGeometry();
348  }
349 
350  updateCloseButtonPosition();
351 }
352 
353 int KonqStatusBarMessageLabel::availableTextWidth() const
354 {
355  const int buttonWidth = (d->m_type == Error) ?
356  d->m_closeButton->width() + BorderGap : 0;
357  return width() - d->m_pixmap.width() - (BorderGap * 4) - buttonWidth;
358 }
359 
360 void KonqStatusBarMessageLabel::updateCloseButtonPosition()
361 {
362  const int x = width() - d->m_closeButton->width() - BorderGap;
363  d->m_closeButton->move(x, 0);
364 }
365 
366 void KonqStatusBarMessageLabel::closeErrorMessage()
367 {
368  if (!showPendingMessage()) {
369  d->m_state = DefaultState;
370  setMessage(d->m_defaultText, Default);
371  }
372 }
373 
374 bool KonqStatusBarMessageLabel::showPendingMessage()
375 {
376  if (!d->m_pendingMessages.isEmpty()) {
377  reset();
378  setMessage(d->m_pendingMessages.takeFirst(), Error);
379  return true;
380  }
381  return false;
382 }
383 
384 void KonqStatusBarMessageLabel::reset()
385 {
386  d->m_text.clear();
387  d->m_type = Default;
388 }
389 
390 QSize KonqStatusBarMessageLabel::sizeHint() const
391 {
392  return minimumSizeHint();
393 }
394 
395 QSize KonqStatusBarMessageLabel::minimumSizeHint() const
396 {
397  const int fontHeight = fontMetrics().height();
398  QSize sz(100, fontHeight);
399  if (d->m_closeButton->isVisible()) {
400  const QSize toolButtonSize = d->m_closeButton->sizeHint();
401  sz = toolButtonSize.expandedTo(sz);
402  }
403  return sz;
404 }
405 
406 #include "konq_statusbarmessagelabel.moc"
KonqStatusBarMessageLabel::KonqStatusBarMessageLabel
KonqStatusBarMessageLabel(QWidget *parent)
Definition: konq_statusbarmessagelabel.cpp:68
GeometryTimeout
Definition: konq_statusbarmessagelabel.cpp:38
QWidget
KonqStatusBarMessageLabel::type
Type type() const
Definition: konq_statusbarmessagelabel.cpp:168
KonqStatusBarMessageLabel::OperationCompleted
Definition: konq_statusbarmessagelabel.h:53
KonqStatusBarMessageLabel::Information
Definition: konq_statusbarmessagelabel.h:54
KonqStatusBarMessageLabel::text
QString text() const
Definition: konq_statusbarmessagelabel.cpp:173
KonqStatusBarMessageLabel::setMinimumTextHeight
void setMinimumTextHeight(int min)
Definition: konq_statusbarmessagelabel.cpp:188
KonqStatusBarMessageLabel::sizeHint
virtual QSize sizeHint() const
Definition: konq_statusbarmessagelabel.cpp:390
KonqStatusBarMessageLabel::paintEvent
virtual void paintEvent(QPaintEvent *event)
Definition: konq_statusbarmessagelabel.cpp:204
KonqStatusBarMessageLabel::~KonqStatusBarMessageLabel
virtual ~KonqStatusBarMessageLabel()
Definition: konq_statusbarmessagelabel.cpp:87
KonqStatusBarMessageLabel::minimumTextHeight
int minimumTextHeight() const
Definition: konq_statusbarmessagelabel.cpp:199
KonqStatusBarMessageLabel::setDefaultText
void setDefaultText(const QString &text)
Definition: konq_statusbarmessagelabel.cpp:178
KonqStatusBarMessageLabel::defaultText
QString defaultText() const
Definition: konq_statusbarmessagelabel.cpp:183
KonqStatusBarMessageLabel::setMessage
void setMessage(const QString &text, Type type)
Definition: konq_statusbarmessagelabel.cpp:92
KonqStatusBarMessageLabel::Default
Definition: konq_statusbarmessagelabel.h:52
KonqStatusBarMessageLabel::Type
Type
Describes the type of the message text.
Definition: konq_statusbarmessagelabel.h:51
KonqStatusBarMessageLabel::Error
Definition: konq_statusbarmessagelabel.h:55
BorderGap
Definition: konq_statusbarmessagelabel.cpp:39
konq_statusbarmessagelabel.h
KonqStatusBarMessageLabel::minimumSizeHint
virtual QSize minimumSizeHint() const
Definition: konq_statusbarmessagelabel.cpp:395
KonqStatusBarMessageLabel::resizeEvent
virtual void resizeEvent(QResizeEvent *event)
Definition: konq_statusbarmessagelabel.cpp:256
QList
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:31:18 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

libkonq

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

applications API Reference

Skip menu "applications API Reference"
  •   kate
  •       kate
  •   KTextEditor
  •   Kate
  • Applications
  •   Libraries
  •     libkonq
  • Konsole

Search



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