KDEUI
kmessagewidget.cpp
Go to the documentation of this file.
00001 /* This file is part of the KDE libraries 00002 * 00003 * Copyright (c) 2011 Aurélien Gâteau <agateau@kde.org> 00004 * 00005 * This library is free software; you can redistribute it and/or 00006 * modify it under the terms of the GNU Lesser General Public 00007 * License as published by the Free Software Foundation; either 00008 * version 2.1 of the License, or (at your option) any later version. 00009 * 00010 * This library is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 * Lesser General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU Lesser General Public 00016 * License along with this library; if not, write to the Free Software 00017 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 00018 * 02110-1301 USA 00019 */ 00020 #include "kmessagewidget.h" 00021 00022 #include <kaction.h> 00023 #include <kcolorscheme.h> 00024 #include <kdebug.h> 00025 #include <kglobalsettings.h> 00026 #include <kicon.h> 00027 #include <kiconloader.h> 00028 #include <kstandardaction.h> 00029 00030 #include <QEvent> 00031 #include <QGridLayout> 00032 #include <QHBoxLayout> 00033 #include <QLabel> 00034 #include <QPainter> 00035 #include <QShowEvent> 00036 #include <QTimeLine> 00037 #include <QToolButton> 00038 00039 //--------------------------------------------------------------------- 00040 // KMessageWidgetPrivate 00041 //--------------------------------------------------------------------- 00042 class KMessageWidgetPrivate 00043 { 00044 public: 00045 void init(KMessageWidget*); 00046 00047 KMessageWidget* q; 00048 QFrame* content; 00049 QLabel* iconLabel; 00050 QLabel* textLabel; 00051 QToolButton* closeButton; 00052 QTimeLine* timeLine; 00053 00054 KMessageWidget::MessageType messageType; 00055 bool wordWrap; 00056 QList<QToolButton*> buttons; 00057 QPixmap contentSnapShot; 00058 00059 void createLayout(); 00060 void updateSnapShot(); 00061 void updateLayout(); 00062 void slotTimeLineChanged(qreal); 00063 void slotTimeLineFinished(); 00064 }; 00065 00066 void KMessageWidgetPrivate::init(KMessageWidget *q_ptr) 00067 { 00068 q = q_ptr; 00069 00070 q->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); 00071 00072 timeLine = new QTimeLine(500, q); 00073 QObject::connect(timeLine, SIGNAL(valueChanged(qreal)), q, SLOT(slotTimeLineChanged(qreal))); 00074 QObject::connect(timeLine, SIGNAL(finished()), q, SLOT(slotTimeLineFinished())); 00075 00076 content = new QFrame(q); 00077 content->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); 00078 00079 wordWrap = false; 00080 00081 iconLabel = new QLabel(content); 00082 iconLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); 00083 00084 textLabel = new QLabel(content); 00085 textLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); 00086 textLabel->setTextInteractionFlags(Qt::TextBrowserInteraction); 00087 00088 KAction* closeAction = KStandardAction::close(q, SLOT(animatedHide()), q); 00089 00090 closeButton = new QToolButton(content); 00091 closeButton->setAutoRaise(true); 00092 closeButton->setDefaultAction(closeAction); 00093 00094 q->setMessageType(KMessageWidget::Information); 00095 } 00096 00097 void KMessageWidgetPrivate::createLayout() 00098 { 00099 delete content->layout(); 00100 00101 content->resize(q->size()); 00102 00103 qDeleteAll(buttons); 00104 buttons.clear(); 00105 00106 Q_FOREACH(QAction* action, q->actions()) { 00107 QToolButton* button = new QToolButton(content); 00108 button->setDefaultAction(action); 00109 button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); 00110 buttons.append(button); 00111 } 00112 00113 // AutoRaise reduces visual clutter, but we don't want to turn it on if 00114 // there are other buttons, otherwise the close button will look different 00115 // from the others. 00116 closeButton->setAutoRaise(buttons.isEmpty()); 00117 00118 if (wordWrap) { 00119 QGridLayout* layout = new QGridLayout(content); 00120 // Set alignment to make sure icon does not move down if text wraps 00121 layout->addWidget(iconLabel, 0, 0, 1, 1, Qt::AlignHCenter | Qt::AlignTop); 00122 layout->addWidget(textLabel, 0, 1); 00123 00124 QHBoxLayout* buttonLayout = new QHBoxLayout; 00125 buttonLayout->addStretch(); 00126 Q_FOREACH(QToolButton* button, buttons) { 00127 // For some reason, calling show() is necessary if wordwrap is true, 00128 // otherwise the buttons do not show up. It is not needed if 00129 // wordwrap is false. 00130 button->show(); 00131 buttonLayout->addWidget(button); 00132 } 00133 buttonLayout->addWidget(closeButton); 00134 layout->addItem(buttonLayout, 1, 0, 1, 2); 00135 } else { 00136 QHBoxLayout* layout = new QHBoxLayout(content); 00137 layout->addWidget(iconLabel); 00138 layout->addWidget(textLabel); 00139 00140 Q_FOREACH(QToolButton* button, buttons) { 00141 layout->addWidget(button); 00142 } 00143 00144 layout->addWidget(closeButton); 00145 }; 00146 00147 if (q->isVisible()) { 00148 q->setFixedHeight(content->sizeHint().height()); 00149 } 00150 q->updateGeometry(); 00151 } 00152 00153 void KMessageWidgetPrivate::updateLayout() 00154 { 00155 if (content->layout()) { 00156 createLayout(); 00157 } 00158 } 00159 00160 void KMessageWidgetPrivate::updateSnapShot() 00161 { 00162 contentSnapShot = QPixmap(content->size()); 00163 contentSnapShot.fill(Qt::transparent); 00164 content->render(&contentSnapShot, QPoint(), QRegion(), QWidget::DrawChildren); 00165 } 00166 00167 void KMessageWidgetPrivate::slotTimeLineChanged(qreal value) 00168 { 00169 q->setFixedHeight(qMin(value * 2, qreal(1.0)) * content->height()); 00170 q->update(); 00171 } 00172 00173 void KMessageWidgetPrivate::slotTimeLineFinished() 00174 { 00175 if (timeLine->direction() == QTimeLine::Forward) { 00176 // Show 00177 content->move(0, 0); 00178 } else { 00179 // Hide 00180 q->hide(); 00181 } 00182 } 00183 00184 00185 //--------------------------------------------------------------------- 00186 // KMessageWidget 00187 //--------------------------------------------------------------------- 00188 KMessageWidget::KMessageWidget(QWidget* parent) 00189 : QFrame(parent) 00190 , d(new KMessageWidgetPrivate) 00191 { 00192 d->init(this); 00193 } 00194 00195 KMessageWidget::KMessageWidget(const QString& text, QWidget* parent) 00196 : QFrame(parent) 00197 , d(new KMessageWidgetPrivate) 00198 { 00199 d->init(this); 00200 setText(text); 00201 } 00202 00203 KMessageWidget::~KMessageWidget() 00204 { 00205 delete d; 00206 } 00207 00208 QString KMessageWidget::text() const 00209 { 00210 return d->textLabel->text(); 00211 } 00212 00213 void KMessageWidget::setText(const QString& text) 00214 { 00215 d->textLabel->setText(text); 00216 updateGeometry(); 00217 } 00218 00219 KMessageWidget::MessageType KMessageWidget::messageType() const 00220 { 00221 return d->messageType; 00222 } 00223 00224 static void getColorsFromColorScheme(KColorScheme::BackgroundRole bgRole, QColor* bg, QColor* fg) 00225 { 00226 KColorScheme scheme(QPalette::Active, KColorScheme::Window); 00227 *bg = scheme.background(bgRole).color(); 00228 *fg = scheme.foreground().color(); 00229 } 00230 00231 void KMessageWidget::setMessageType(KMessageWidget::MessageType type) 00232 { 00233 d->messageType = type; 00234 KIcon icon; 00235 QColor bg0, bg1, bg2, border, fg; 00236 switch (type) { 00237 case Positive: 00238 icon = KIcon("dialog-ok"); 00239 getColorsFromColorScheme(KColorScheme::PositiveBackground, &bg1, &fg); 00240 break; 00241 case Information: 00242 icon = KIcon("dialog-information"); 00243 // There is no "information" background role in KColorScheme, use the 00244 // colors of highlighted items instead 00245 bg1 = palette().highlight().color(); 00246 fg = palette().highlightedText().color(); 00247 break; 00248 case Warning: 00249 icon = KIcon("dialog-warning"); 00250 getColorsFromColorScheme(KColorScheme::NeutralBackground, &bg1, &fg); 00251 break; 00252 case Error: 00253 icon = KIcon("dialog-error"); 00254 getColorsFromColorScheme(KColorScheme::NegativeBackground, &bg1, &fg); 00255 break; 00256 } 00257 00258 // Colors 00259 bg0 = bg1.lighter(110); 00260 bg2 = bg1.darker(110); 00261 border = KColorScheme::shade(bg1, KColorScheme::DarkShade); 00262 00263 d->content->setStyleSheet( 00264 QString(".QFrame {" 00265 "background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1," 00266 " stop: 0 %1," 00267 " stop: 0.1 %2," 00268 " stop: 1.0 %3);" 00269 "border-radius: 5px;" 00270 "border: 1px solid %4;" 00271 "}" 00272 ".QLabel { color: %5; }" 00273 ) 00274 .arg(bg0.name()) 00275 .arg(bg1.name()) 00276 .arg(bg2.name()) 00277 .arg(border.name()) 00278 .arg(fg.name()) 00279 ); 00280 00281 // Icon 00282 const int size = KIconLoader::global()->currentSize(KIconLoader::MainToolbar); 00283 d->iconLabel->setPixmap(icon.pixmap(size)); 00284 } 00285 00286 QSize KMessageWidget::sizeHint() const 00287 { 00288 ensurePolished(); 00289 return d->content->sizeHint(); 00290 } 00291 00292 QSize KMessageWidget::minimumSizeHint() const 00293 { 00294 ensurePolished(); 00295 return d->content->minimumSizeHint(); 00296 } 00297 00298 bool KMessageWidget::event(QEvent* event) 00299 { 00300 if (event->type() == QEvent::Polish && !d->content->layout()) { 00301 d->createLayout(); 00302 } 00303 return QFrame::event(event); 00304 } 00305 00306 void KMessageWidget::resizeEvent(QResizeEvent* event) 00307 { 00308 QFrame::resizeEvent(event); 00309 if (d->timeLine->state() == QTimeLine::NotRunning) { 00310 int contentHeight = d->content->heightForWidth(width()); 00311 if (contentHeight == -1) { 00312 contentHeight = d->content->sizeHint().height(); 00313 } 00314 d->content->resize(width(), contentHeight); 00315 } 00316 } 00317 00318 int KMessageWidget::heightForWidth(int width) const 00319 { 00320 ensurePolished(); 00321 return d->content->heightForWidth(width); 00322 } 00323 00324 void KMessageWidget::paintEvent(QPaintEvent* event) 00325 { 00326 QFrame::paintEvent(event); 00327 if (d->timeLine->state() == QTimeLine::Running) { 00328 QPainter painter(this); 00329 painter.setOpacity(d->timeLine->currentValue() * d->timeLine->currentValue()); 00330 painter.drawPixmap(0, 0, d->contentSnapShot); 00331 } 00332 } 00333 00334 void KMessageWidget::showEvent(QShowEvent* event) 00335 { 00336 // Keep this method here to avoid breaking binary compatibility: 00337 // QFrame::showEvent() used to be reimplemented. 00338 QFrame::showEvent(event); 00339 } 00340 00341 bool KMessageWidget::wordWrap() const 00342 { 00343 return d->wordWrap; 00344 } 00345 00346 void KMessageWidget::setWordWrap(bool wordWrap) 00347 { 00348 d->wordWrap = wordWrap; 00349 d->textLabel->setWordWrap(wordWrap); 00350 d->updateLayout(); 00351 } 00352 00353 bool KMessageWidget::isCloseButtonVisible() const 00354 { 00355 return d->closeButton->isVisible(); 00356 } 00357 00358 void KMessageWidget::setCloseButtonVisible(bool show) 00359 { 00360 d->closeButton->setVisible(show); 00361 } 00362 00363 void KMessageWidget::addAction(QAction* action) 00364 { 00365 QFrame::addAction(action); 00366 d->updateLayout(); 00367 } 00368 00369 void KMessageWidget::removeAction(QAction* action) 00370 { 00371 QFrame::removeAction(action); 00372 d->updateLayout(); 00373 } 00374 00375 void KMessageWidget::animatedShow() 00376 { 00377 if (!(KGlobalSettings::graphicEffectsLevel() & KGlobalSettings::SimpleAnimationEffects)) { 00378 show(); 00379 return; 00380 } 00381 00382 if (isVisible()) { 00383 return; 00384 } 00385 00386 QFrame::show(); 00387 setFixedHeight(0); 00388 int wantedHeight = d->content->sizeHint().height(); 00389 d->content->setGeometry(0, -wantedHeight, width(), wantedHeight); 00390 00391 d->updateSnapShot(); 00392 00393 d->timeLine->setDirection(QTimeLine::Forward); 00394 if (d->timeLine->state() == QTimeLine::NotRunning) { 00395 d->timeLine->start(); 00396 } 00397 } 00398 00399 void KMessageWidget::animatedHide() 00400 { 00401 if (!(KGlobalSettings::graphicEffectsLevel() & KGlobalSettings::SimpleAnimationEffects)) { 00402 hide(); 00403 return; 00404 } 00405 00406 if (!isVisible()) { 00407 return; 00408 } 00409 00410 d->content->move(0, -d->content->height()); 00411 d->updateSnapShot(); 00412 00413 d->timeLine->setDirection(QTimeLine::Backward); 00414 if (d->timeLine->state() == QTimeLine::NotRunning) { 00415 d->timeLine->start(); 00416 } 00417 } 00418 00419 #include "kmessagewidget.moc"
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Wed Nov 28 2012 09:48:21 by doxygen 1.7.5 written by Dimitri van Heesch, © 1997-2006
Documentation copyright © 1996-2012 The KDE developers.
Generated on Wed Nov 28 2012 09:48:21 by doxygen 1.7.5 written by Dimitri van Heesch, © 1997-2006
KDE's Doxygen guidelines are available online.