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 // Only set autoRaise on if there are no buttons, otherwise the close 00114 // button looks weird 00115 closeButton->setAutoRaise(buttons.isEmpty()); 00116 00117 if (wordWrap) { 00118 QGridLayout* layout = new QGridLayout(content); 00119 layout->addWidget(iconLabel, 0, 0); 00120 layout->addWidget(textLabel, 0, 1); 00121 00122 QHBoxLayout* buttonLayout = new QHBoxLayout; 00123 buttonLayout->addStretch(); 00124 Q_FOREACH(QToolButton* button, buttons) { 00125 // For some reason, calling show() is necessary here, but not in 00126 // wordwrap mode 00127 button->show(); 00128 buttonLayout->addWidget(button); 00129 } 00130 buttonLayout->addWidget(closeButton); 00131 layout->addItem(buttonLayout, 1, 0, 1, 2); 00132 } else { 00133 QHBoxLayout* layout = new QHBoxLayout(content); 00134 layout->addWidget(iconLabel); 00135 layout->addWidget(textLabel); 00136 00137 Q_FOREACH(QToolButton* button, buttons) { 00138 layout->addWidget(button); 00139 } 00140 00141 layout->addWidget(closeButton); 00142 }; 00143 00144 if (q->isVisible()) { 00145 q->setFixedHeight(content->sizeHint().height()); 00146 } 00147 q->updateGeometry(); 00148 } 00149 00150 void KMessageWidgetPrivate::updateLayout() 00151 { 00152 if (content->layout()) { 00153 createLayout(); 00154 } 00155 } 00156 00157 void KMessageWidgetPrivate::updateSnapShot() 00158 { 00159 contentSnapShot = QPixmap(content->size()); 00160 contentSnapShot.fill(Qt::transparent); 00161 content->render(&contentSnapShot, QPoint(), QRegion(), QWidget::DrawChildren); 00162 } 00163 00164 void KMessageWidgetPrivate::slotTimeLineChanged(qreal value) 00165 { 00166 q->setFixedHeight(qMin(value * 2, qreal(1.0)) * content->height()); 00167 q->update(); 00168 } 00169 00170 void KMessageWidgetPrivate::slotTimeLineFinished() 00171 { 00172 if (timeLine->direction() == QTimeLine::Forward) { 00173 // Show 00174 content->move(0, 0); 00175 } else { 00176 // Hide 00177 q->hide(); 00178 } 00179 } 00180 00181 00182 //--------------------------------------------------------------------- 00183 // KMessageWidget 00184 //--------------------------------------------------------------------- 00185 KMessageWidget::KMessageWidget(QWidget* parent) 00186 : QFrame(parent) 00187 , d(new KMessageWidgetPrivate) 00188 { 00189 d->init(this); 00190 } 00191 00192 KMessageWidget::KMessageWidget(const QString& text, QWidget* parent) 00193 : QFrame(parent) 00194 , d(new KMessageWidgetPrivate) 00195 { 00196 d->init(this); 00197 setText(text); 00198 } 00199 00200 KMessageWidget::~KMessageWidget() 00201 { 00202 delete d; 00203 } 00204 00205 QString KMessageWidget::text() const 00206 { 00207 return d->textLabel->text(); 00208 } 00209 00210 void KMessageWidget::setText(const QString& text) 00211 { 00212 d->textLabel->setText(text); 00213 updateGeometry(); 00214 } 00215 00216 KMessageWidget::MessageType KMessageWidget::messageType() const 00217 { 00218 return d->messageType; 00219 } 00220 00221 void KMessageWidget::setMessageType(KMessageWidget::MessageType type) 00222 { 00223 d->messageType = type; 00224 KIcon icon; 00225 KColorScheme::BackgroundRole bgRole; 00226 KColorScheme::ForegroundRole fgRole; 00227 KColorScheme::ColorSet colorSet = KColorScheme::Window; 00228 switch (type) { 00229 case Positive: 00230 icon = KIcon("dialog-ok"); 00231 bgRole = KColorScheme::PositiveBackground; 00232 fgRole = KColorScheme::PositiveText; 00233 break; 00234 case Information: 00235 icon = KIcon("dialog-information"); 00236 bgRole = KColorScheme::NormalBackground; 00237 fgRole = KColorScheme::NormalText; 00238 colorSet = KColorScheme::Tooltip; 00239 break; 00240 case Warning: 00241 icon = KIcon("dialog-warning"); 00242 bgRole = KColorScheme::NeutralBackground; 00243 fgRole = KColorScheme::NeutralText; 00244 break; 00245 case Error: 00246 icon = KIcon("dialog-error"); 00247 bgRole = KColorScheme::NegativeBackground; 00248 fgRole = KColorScheme::NegativeText; 00249 break; 00250 } 00251 const int size = KIconLoader::global()->currentSize(KIconLoader::MainToolbar); 00252 d->iconLabel->setPixmap(icon.pixmap(size)); 00253 00254 KColorScheme scheme(QPalette::Active, colorSet); 00255 QBrush bg = scheme.background(bgRole); 00256 QBrush border = scheme.foreground(fgRole); 00257 QBrush fg = scheme.foreground(); 00258 d->content->setStyleSheet( 00259 QString(".QFrame {" 00260 "background-color: %1;" 00261 "border-radius: 5px;" 00262 "border: 1px solid %2;" 00263 "}" 00264 ".QLabel { color: %3; }" 00265 ) 00266 .arg(bg.color().name()) 00267 .arg(border.color().name()) 00268 .arg(fg.color().name()) 00269 ); 00270 } 00271 00272 QSize KMessageWidget::sizeHint() const 00273 { 00274 ensurePolished(); 00275 return d->content->sizeHint(); 00276 } 00277 00278 QSize KMessageWidget::minimumSizeHint() const 00279 { 00280 ensurePolished(); 00281 return d->content->minimumSizeHint(); 00282 } 00283 00284 bool KMessageWidget::event(QEvent* event) 00285 { 00286 if (event->type() == QEvent::Polish && !d->content->layout()) { 00287 d->createLayout(); 00288 } 00289 return QFrame::event(event); 00290 } 00291 00292 void KMessageWidget::resizeEvent(QResizeEvent* event) 00293 { 00294 QFrame::resizeEvent(event); 00295 if (d->timeLine->state() == QTimeLine::NotRunning) { 00296 d->content->resize(size()); 00297 } 00298 } 00299 00300 void KMessageWidget::paintEvent(QPaintEvent* event) 00301 { 00302 QFrame::paintEvent(event); 00303 if (d->timeLine->state() == QTimeLine::Running) { 00304 QPainter painter(this); 00305 painter.setOpacity(d->timeLine->currentValue() * d->timeLine->currentValue()); 00306 painter.drawPixmap(0, 0, d->contentSnapShot); 00307 } 00308 } 00309 00310 void KMessageWidget::showEvent(QShowEvent* event) 00311 { 00312 QFrame::showEvent(event); 00313 if (!event->spontaneous()) { 00314 int wantedHeight = d->content->sizeHint().height(); 00315 d->content->setGeometry(0, 0, width(), wantedHeight); 00316 setFixedHeight(wantedHeight); 00317 } 00318 } 00319 00320 bool KMessageWidget::wordWrap() const 00321 { 00322 return d->wordWrap; 00323 } 00324 00325 void KMessageWidget::setWordWrap(bool wordWrap) 00326 { 00327 d->wordWrap = wordWrap; 00328 d->textLabel->setWordWrap(wordWrap); 00329 d->updateLayout(); 00330 } 00331 00332 bool KMessageWidget::isCloseButtonVisible() const 00333 { 00334 return d->closeButton->isVisible(); 00335 } 00336 00337 void KMessageWidget::setCloseButtonVisible(bool show) 00338 { 00339 d->closeButton->setVisible(show); 00340 } 00341 00342 void KMessageWidget::addAction(QAction* action) 00343 { 00344 QFrame::addAction(action); 00345 d->updateLayout(); 00346 } 00347 00348 void KMessageWidget::removeAction(QAction* action) 00349 { 00350 QFrame::removeAction(action); 00351 d->updateLayout(); 00352 } 00353 00354 void KMessageWidget::animatedShow() 00355 { 00356 if (!(KGlobalSettings::graphicEffectsLevel() & KGlobalSettings::SimpleAnimationEffects)) { 00357 show(); 00358 return; 00359 } 00360 00361 if (isVisible()) { 00362 return; 00363 } 00364 00365 QFrame::show(); 00366 setFixedHeight(0); 00367 int wantedHeight = d->content->sizeHint().height(); 00368 d->content->setGeometry(0, -wantedHeight, width(), wantedHeight); 00369 00370 d->updateSnapShot(); 00371 00372 d->timeLine->setDirection(QTimeLine::Forward); 00373 if (d->timeLine->state() == QTimeLine::NotRunning) { 00374 d->timeLine->start(); 00375 } 00376 } 00377 00378 void KMessageWidget::animatedHide() 00379 { 00380 if (!(KGlobalSettings::graphicEffectsLevel() & KGlobalSettings::SimpleAnimationEffects)) { 00381 hide(); 00382 return; 00383 } 00384 00385 if (!isVisible()) { 00386 return; 00387 } 00388 00389 d->content->move(0, -d->content->height()); 00390 d->updateSnapShot(); 00391 00392 d->timeLine->setDirection(QTimeLine::Backward); 00393 if (d->timeLine->state() == QTimeLine::NotRunning) { 00394 d->timeLine->start(); 00395 } 00396 } 00397 00398 #include "kmessagewidget.moc"
KDE 4.7 API Reference