File indexing completed on 2024-05-12 16:39:57
0001 /* This file is part of the KDE libraries 0002 * 0003 * Copyright (c) 2011 Aurélien Gâteau <agateau@kde.org> 0004 * Copyright (C) 2011-2013 Jarosław Staniek <staniek@kde.org> 0005 * 0006 * This library is free software; you can redistribute it and/or 0007 * modify it under the terms of the GNU Lesser General Public 0008 * License as published by the Free Software Foundation; either 0009 * version 2.1 of the License, or (at your option) any later version. 0010 * 0011 * This library is distributed in the hope that it will be useful, 0012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0014 * Lesser General Public License for more details. 0015 * 0016 * You should have received a copy of the GNU Lesser General Public 0017 * License along with this library; if not, write to the Free Software 0018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 0019 * 02110-1301 USA 0020 */ 0021 #include "kmessagewidget.h" 0022 #include "kmessagewidget_p.h" 0023 0024 #include "KexiCloseButton.h" 0025 #include "KexiIcon.h" 0026 #include <kexiutils/utils.h> 0027 0028 #include <KColorScheme> 0029 #include <KStandardAction> 0030 #include <KStandardGuiItem> 0031 0032 #include <QDebug> 0033 #include <QEvent> 0034 #include <QGridLayout> 0035 #include <QHBoxLayout> 0036 #include <QPainter> 0037 #include <QShowEvent> 0038 #include <QTimeLine> 0039 #include <QToolButton> 0040 #include <QPointer> 0041 #include <QPainterPath> 0042 #include <QTimer> 0043 #include <QAction> 0044 0045 static const int LAYOUT_SPACING = 6; 0046 0047 ClickableLabel::ClickableLabel(QWidget *parent) 0048 : QLabel(parent) 0049 { 0050 } 0051 0052 ClickableLabel::~ClickableLabel() 0053 { 0054 } 0055 0056 void ClickableLabel::mousePressEvent(QMouseEvent *ev) 0057 { 0058 if (ev->button() == Qt::LeftButton) { 0059 emit clicked(); 0060 } 0061 QLabel::mousePressEvent(ev); 0062 } 0063 0064 //--------------------------------------------------------------------- 0065 // KMessageWidgetFrame 0066 //--------------------------------------------------------------------- 0067 0068 KMessageWidgetFrame::KMessageWidgetFrame(QWidget* parent) 0069 : QFrame(parent), radius(7), 0070 m_calloutPointerDirection(KMessageWidget::NoPointer), 0071 m_sizeForRecentTransformation(-1, -1), 0072 m_calloutPointerGlobalPosition(-QWIDGETSIZE_MAX, -QWIDGETSIZE_MAX) 0073 { 0074 const qreal rad = radius; 0075 m_polyline << QPointF(0, 0) 0076 << QPointF(0, rad * 2.0) //<< QPointF(rad, rad * 2.0 - 0.5) 0077 << QPointF(rad * 2.0, 0); 0078 m_polygon << QPointF(m_polyline[0].x(), m_polyline[0].y() - 1) 0079 << QPointF(m_polyline[1].x(), m_polyline[1].y() - 1) 0080 << QPointF(m_polyline[2].x(), m_polyline[2].y() - 1); 0081 } 0082 0083 void KMessageWidgetFrame::paintEvent(QPaintEvent* event) 0084 { 0085 QFrame::paintEvent(event); 0086 paintCalloutPointer(); 0087 } 0088 0089 KMessageWidget::CalloutPointerDirection KMessageWidgetFrame::calloutPointerDirection() const 0090 { 0091 return m_calloutPointerDirection; 0092 } 0093 0094 void KMessageWidgetFrame::setCalloutPointerDirection( 0095 KMessageWidget::CalloutPointerDirection direction) 0096 { 0097 m_calloutPointerDirection = direction; 0098 m_sizeForRecentTransformation = QSize(-1, -1); 0099 } 0100 0101 void KMessageWidgetFrame::updateCalloutPointerTransformation() const 0102 { 0103 if (m_sizeForRecentTransformation == parentWidget()->size()) 0104 return; 0105 0106 m_calloutPointerTransformation.reset(); 0107 0108 const QSizeF s(parentWidget()->size()); 0109 m_sizeForRecentTransformation = parentWidget()->size(); 0110 // qDebug() << size() << parentWidget()->size(); 0111 const qreal rad = radius; 0112 // Original: [v ] 0113 // [ ] 0114 switch (m_calloutPointerDirection) { 0115 case KMessageWidget::Up: 0116 // ^ 0117 // [ ] 0118 m_calloutPointerTransformation 0119 .rotate(180.0) 0120 .translate(- rad * 5.0 + 0.5, - rad * 2 - 0.5) 0121 .scale(-1.0, 1.0); 0122 break; 0123 case KMessageWidget::Down: 0124 // [ ] 0125 // v 0126 // No rotation needed, this is original position of polyline below 0127 m_calloutPointerTransformation 0128 .translate(rad * 3.0 + 0.5, s.height() - rad * 2); 0129 break; 0130 case KMessageWidget::Left: 0131 // <[ ] 0132 // [ ] 0133 m_calloutPointerTransformation 0134 .rotate(90.0) 0135 .translate(rad * 1.5, - rad * 2 - 3.5); 0136 break; 0137 case KMessageWidget::Right: 0138 // [ ]> 0139 // [ ] 0140 m_calloutPointerTransformation 0141 .rotate(-90.0) 0142 .translate(- rad * 1.5, s.width() - rad * 2 - 3.5) 0143 .scale(-1.0, 1.0); 0144 break; 0145 default: 0146 break; 0147 } 0148 } 0149 0150 void KMessageWidgetFrame::setCalloutPointerPosition(const QPoint& globalPos) 0151 { 0152 m_calloutPointerGlobalPosition = globalPos; 0153 updateCalloutPointerPosition(); 0154 } 0155 0156 QPoint KMessageWidgetFrame::calloutPointerPosition() const 0157 { 0158 return m_calloutPointerGlobalPosition; 0159 } 0160 0161 void KMessageWidgetFrame::updateCalloutPointerPosition() const 0162 { 0163 if (m_calloutPointerGlobalPosition == QPoint(-QWIDGETSIZE_MAX, -QWIDGETSIZE_MAX)) 0164 return; 0165 QWidget *messageWidgetParent = parentWidget()->parentWidget(); 0166 if (messageWidgetParent) { 0167 /* qDebug() << "m_calloutPointerGlobalPosition:" << m_calloutPointerGlobalPosition 0168 << "pos():" << pos() 0169 << "pointerPosition():" << pointerPosition() 0170 << "(m_calloutPointerGlobalPosition - pos() - pointerPosition()):" 0171 << (m_calloutPointerGlobalPosition - pos() - pointerPosition()) 0172 << "messageWidgetParent->mapFromGlobal():" 0173 << messageWidgetParent->mapFromGlobal( 0174 m_calloutPointerGlobalPosition - pos() - pointerPosition());*/ 0175 parentWidget()->move( 0176 messageWidgetParent->mapFromGlobal( 0177 m_calloutPointerGlobalPosition - pos() - pointerPosition()) 0178 ); 0179 } 0180 } 0181 0182 void KMessageWidgetFrame::paintCalloutPointer() 0183 { 0184 updateCalloutPointerTransformation(); 0185 0186 if (m_calloutPointerTransformation.isIdentity()) 0187 return; 0188 QPainter painter(this); 0189 painter.setTransform(m_calloutPointerTransformation); 0190 0191 painter.setRenderHint(QPainter::Antialiasing); 0192 painter.setPen(QPen(bgBrush.color(), 1.0)); 0193 painter.setBrush(bgBrush); 0194 painter.drawPolygon(m_polygon); 0195 painter.setPen(QPen(borderBrush, 1.0)); 0196 painter.drawPolyline(m_polyline); 0197 } 0198 0199 QPoint KMessageWidgetFrame::pointerPosition() const 0200 { 0201 updateCalloutPointerTransformation(); 0202 //qDebug() << "MAPPED:" << t.map(polyline[1]) << mapToGlobal(t.map(polyline[1]).toPoint()); 0203 return m_calloutPointerTransformation.map(m_polyline[1]).toPoint(); 0204 } 0205 0206 //--------------------------------------------------------------------- 0207 // KMessageWidgetPrivate 0208 //--------------------------------------------------------------------- 0209 class KMessageWidgetPrivate 0210 { 0211 public: 0212 KMessageWidgetPrivate(); 0213 void init(KMessageWidget*); 0214 0215 KMessageWidget* q; 0216 KMessageWidgetFrame* content; 0217 ClickableLabel* iconLabel; 0218 ClickableLabel* textLabel; 0219 KexiCloseButton* closeButton; 0220 QTimeLine* timeLine; 0221 0222 KMessageWidget::MessageType messageType; 0223 bool wordWrap; 0224 QList<QToolButton*> buttons; 0225 QPixmap contentSnapShot; 0226 QAction* defaultAction; 0227 QPointer<QToolButton> defaultButton; 0228 QSet<QAction*> leftAlignedButtons; 0229 KColorScheme::ColorSet colorSet; 0230 KColorScheme::BackgroundRole bgRole; 0231 KColorScheme::ForegroundRole fgRole; 0232 bool autoDelete; 0233 QWidget* contentsWidget; 0234 bool clickClosesMessage; 0235 bool resizeToContentsOnTimeLineFinished; 0236 0237 void createLayout(); 0238 void updateSnapShot(); 0239 void updateLayout(); 0240 void updateStyleSheet(); 0241 }; 0242 0243 KMessageWidgetPrivate::KMessageWidgetPrivate() 0244 : contentsWidget(0) 0245 { 0246 } 0247 0248 void KMessageWidgetPrivate::init(KMessageWidget *q_ptr) 0249 { 0250 q = q_ptr; 0251 0252 q->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); 0253 0254 timeLine = new QTimeLine(500, q); 0255 QObject::connect(timeLine, SIGNAL(valueChanged(qreal)), q, SLOT(slotTimeLineChanged(qreal))); 0256 QObject::connect(timeLine, SIGNAL(finished()), q, SLOT(slotTimeLineFinished())); 0257 0258 content = new KMessageWidgetFrame(q); 0259 content->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); 0260 0261 wordWrap = false; 0262 resizeToContentsOnTimeLineFinished = false; 0263 0264 if (contentsWidget) { 0265 iconLabel = 0; 0266 textLabel = 0; 0267 } 0268 else { 0269 iconLabel = new ClickableLabel(content); 0270 iconLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum); 0271 QObject::connect(iconLabel, SIGNAL(clicked()), q, SLOT(tryClickCloseMessage())); 0272 0273 textLabel = new ClickableLabel(content); 0274 textLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); 0275 textLabel->setTextInteractionFlags(Qt::TextBrowserInteraction); 0276 textLabel->setContentsMargins(0, 0, 0, 0); 0277 QObject::connect(textLabel, SIGNAL(clicked()), q, SLOT(tryClickCloseMessage())); 0278 #if 0 0279 content->setAutoFillBackground(true); 0280 content->setBackgroundRole(QPalette::Dark); 0281 textLabel->setAutoFillBackground(true); 0282 textLabel->setBackgroundRole(QPalette::Mid); 0283 #endif 0284 } 0285 closeButton = new KexiCloseButton(content); 0286 QObject::connect(closeButton, SIGNAL(clicked()), q, SLOT(animatedHide())); 0287 0288 defaultAction = 0; 0289 autoDelete = false; 0290 clickClosesMessage = false; 0291 q->setMessageType(KMessageWidget::Information); 0292 } 0293 0294 void KMessageWidgetPrivate::createLayout() 0295 { 0296 delete content->layout(); 0297 0298 content->resize(q->size()); 0299 0300 qDeleteAll(buttons); 0301 buttons.clear(); 0302 0303 QList<QToolButton*> buttonsTabOrder; 0304 Q_FOREACH(QAction* action, q->actions()) { 0305 QToolButton* button = new QToolButton(content); 0306 button->setDefaultAction(action); 0307 button->setFocusPolicy(Qt::StrongFocus); 0308 button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); 0309 buttons.append(button); 0310 if (defaultAction == action) { 0311 buttonsTabOrder.prepend(button); // default button is focused first 0312 q->setFocusProxy(button); 0313 defaultButton = button; 0314 } 0315 else 0316 buttonsTabOrder.append(button); 0317 } 0318 QToolButton *previousButton = 0; 0319 Q_FOREACH(QToolButton* button, buttonsTabOrder) { 0320 if (previousButton) 0321 QWidget::setTabOrder(previousButton, button); 0322 previousButton = button; 0323 } 0324 0325 // Only set autoRaise on if there are no buttons, otherwise the close 0326 // button looks weird 0327 //closeButton->setAutoRaise(buttons.isEmpty()); 0328 0329 QHBoxLayout* buttonLayout = 0; 0330 int leftContentSpacerItemWidth = LAYOUT_SPACING; 0331 int rightContentSpacerItemWidth = LAYOUT_SPACING; 0332 int bottomContentSpacerItemHeight = LAYOUT_SPACING; 0333 switch (content->calloutPointerDirection()) { 0334 case KMessageWidget::Up: 0335 break; 0336 case KMessageWidget::Down: 0337 bottomContentSpacerItemHeight = content->radius * 2 + LAYOUT_SPACING; 0338 break; 0339 case KMessageWidget::Left: 0340 leftContentSpacerItemWidth = content->radius * 2 + LAYOUT_SPACING; 0341 break; 0342 case KMessageWidget::Right: 0343 rightContentSpacerItemWidth = content->radius * 2 + LAYOUT_SPACING; 0344 break; 0345 default:; 0346 } 0347 if (wordWrap) { 0348 QGridLayout* layout = new QGridLayout(content); 0349 layout->setSpacing(LAYOUT_SPACING); 0350 if (contentsWidget) { 0351 layout->addItem(new QSpacerItem(leftContentSpacerItemWidth, LAYOUT_SPACING), 0, 0); 0352 layout->addWidget(contentsWidget, 1, 0, 1, 2); 0353 layout->addItem(new QSpacerItem(rightContentSpacerItemWidth, LAYOUT_SPACING), 3, 0); 0354 0355 /* if (contentsWidget->maximumWidth() < QWIDGETSIZE_MAX 0356 && contentsWidget->maximumHeight() < QWIDGETSIZE_MAX 0357 && contentsWidget->maximumSize() == contentsWidget->minimumSize()) 0358 { 0359 qDebug() << "contentsWidget->maximumSize():" << contentsWidget->maximumSize(); 0360 qDebug() << "content->size():" << content->size(); 0361 contentsWidget->setFixedSize( 0362 contentsWidget->maximumSize() - QSize(120, 0)); 0363 //q->setFixedSize( 0364 // contentsWidget->maximumSize() + QSize(100, 0)); 0365 0366 qFatal() << contentsWidget->maximumSize(); 0367 }*/ 0368 } 0369 else { 0370 layout->addItem(new QSpacerItem(leftContentSpacerItemWidth, LAYOUT_SPACING), 0, 0); 0371 layout->addWidget(iconLabel, 1, 1, Qt::AlignCenter | Qt::AlignTop); 0372 //iconLabel->setContentsMargins(0, LAYOUT_SPACING, 0, 0); 0373 iconLabel->setAlignment(Qt::AlignCenter | Qt::AlignTop); 0374 layout->addWidget(textLabel, 1, 2); 0375 textLabel->setAlignment(Qt::AlignLeft | Qt::AlignTop); 0376 layout->addItem(new QSpacerItem(rightContentSpacerItemWidth, LAYOUT_SPACING), 0, 3); 0377 } 0378 0379 buttonLayout = new QHBoxLayout; 0380 buttonLayout->setSpacing(LAYOUT_SPACING); 0381 bool stretchAdded = false; 0382 Q_FOREACH(QToolButton* button, buttons) { 0383 if (!stretchAdded && !leftAlignedButtons.contains(button->defaultAction())) { 0384 buttonLayout->addStretch(); 0385 stretchAdded = true; 0386 } 0387 // For some reason, calling show() is necessary here, but not in 0388 // wordwrap mode 0389 button->show(); 0390 buttonLayout->addWidget(button); 0391 } 0392 if (contentsWidget) { 0393 buttonLayout->addStretch(); 0394 buttonLayout->addWidget(closeButton); 0395 buttonLayout->setContentsMargins(0, 10, 0, 0); 0396 layout->addLayout(buttonLayout, 0, 0); 0397 } 0398 else { 0399 buttonLayout->addWidget(closeButton); 0400 //?? buttonLayout->setContentsMargins(0, 10, 0, 0); 0401 layout->addItem(buttonLayout, 2, 1, 1, 2); 0402 layout->addItem(new QSpacerItem(rightContentSpacerItemWidth, bottomContentSpacerItemHeight), 3, 3); 0403 } 0404 } else { 0405 QHBoxLayout* layout = new QHBoxLayout(content); 0406 layout->setSpacing(LAYOUT_SPACING); 0407 if (contentsWidget) { 0408 layout->addWidget(contentsWidget); 0409 } 0410 else { 0411 layout->addWidget(iconLabel); 0412 layout->addWidget(textLabel); 0413 } 0414 Q_FOREACH(QToolButton* button, buttons) { 0415 layout->addWidget(button); 0416 } 0417 0418 layout->addWidget(closeButton); 0419 }; 0420 0421 // add margins based on outer margins 0422 int left, top, right, bottom; 0423 q->getContentsMargins(&left, &top, &right, &bottom); 0424 //qDebug() << "q->getContentsMargins:" << left << top << right << bottom; 0425 switch (content->calloutPointerDirection()) { 0426 case KMessageWidget::Up: 0427 left += 1; 0428 top += 4; 0429 bottom += 4; 0430 right += 2; 0431 if (!buttons.isEmpty()) { 0432 top += 4; 0433 right += 3; 0434 } 0435 break; 0436 case KMessageWidget::Down: 0437 left += 1; 0438 top += 4; 0439 bottom += 4; 0440 right += 2; 0441 if (!buttons.isEmpty()) { 0442 right += 3; 0443 } 0444 break; 0445 case KMessageWidget::Left: { 0446 left += 0; 0447 top += 3; 0448 bottom += 3; 0449 right += 1; 0450 if (buttonLayout) { 0451 int leftSp = content->radius * 2 + LAYOUT_SPACING; 0452 buttonLayout->insertSpacing(0, leftSp); 0453 buttonLayout->addSpacing(LAYOUT_SPACING); 0454 } 0455 break; 0456 } 0457 case KMessageWidget::Right: 0458 left += 0; 0459 top += 3; 0460 bottom += 3; 0461 right += 1; 0462 break; 0463 default:; 0464 } 0465 content->layout()->setContentsMargins( 0466 left, top, right, bottom); 0467 0468 if (q->isVisible()) { 0469 if (content->sizeHint().height() >= 0) { 0470 //q->setFixedHeight(content->sizeHint().height()); 0471 q->setFixedHeight(QWIDGETSIZE_MAX); 0472 } 0473 } 0474 content->updateGeometry(); 0475 q->updateGeometry(); 0476 } 0477 0478 void KMessageWidgetPrivate::updateLayout() 0479 { 0480 if (content->layout()) { 0481 createLayout(); 0482 } 0483 } 0484 0485 void KMessageWidgetPrivate::updateSnapShot() 0486 { 0487 contentSnapShot = QPixmap(content->size()); 0488 contentSnapShot.fill(Qt::transparent); 0489 content->render(&contentSnapShot, QPoint(), QRegion(), QWidget::DrawChildren); 0490 } 0491 0492 void KMessageWidgetPrivate::updateStyleSheet() 0493 { 0494 KColorScheme scheme(QPalette::Active, colorSet); 0495 content->bgBrush = scheme.background(bgRole); 0496 content->borderBrush = scheme.foreground(fgRole); 0497 QBrush fg = scheme.foreground(); 0498 0499 int left, top, right, bottom; 0500 content->getContentsMargins(&left, &top, &right, &bottom); 0501 //qDebug() << "content->getContentsMargins:" << left << top << right << bottom; 0502 if (!buttons.isEmpty()) { 0503 //q->setContentsMargins(0, 0, 0, 0); 0504 content->setContentsMargins(LAYOUT_SPACING, 0, 0, 0); 0505 } 0506 q->getContentsMargins(&left, &top, &right, &bottom); 0507 //qDebug() << "q->getContentsMargins:" << left << top << right << bottom; 0508 #if 1 0509 int add = content->radius * 2; 0510 switch (content->calloutPointerDirection()) { 0511 case KMessageWidget::Up: 0512 top += add; 0513 break; 0514 case KMessageWidget::Down: 0515 bottom += add; 0516 break; 0517 case KMessageWidget::Left: 0518 left += add; 0519 break; 0520 case KMessageWidget::Right: 0521 right += add; 0522 break; 0523 default:; 0524 } 0525 content->setStyleSheet( 0526 QString(".KMessageWidgetFrame {" 0527 "background-color: %1;" 0528 "border-radius: %2px;" 0529 "margin: %3px %4px %5px %6px;" 0530 "border: 1px solid %7;" 0531 "}" 0532 ".QLabel { color: %8; }" 0533 ) 0534 .arg(content->bgBrush.color().name()) 0535 .arg(content->radius) 0536 .arg(top) 0537 .arg(right) 0538 .arg(bottom) 0539 .arg(left) 0540 .arg(content->borderBrush.color().name()) 0541 .arg(fg.color().name()) 0542 ); 0543 closeButton->setStyle(QApplication::style()); // clear stylesheets style from this button 0544 #endif 0545 } 0546 0547 //--------------------------------------------------------------------- 0548 // KMessageWidget 0549 //--------------------------------------------------------------------- 0550 KMessageWidget::KMessageWidget(QWidget* parent) 0551 : QFrame(parent) 0552 , d(new KMessageWidgetPrivate) 0553 { 0554 d->init(this); 0555 } 0556 0557 KMessageWidget::KMessageWidget(const QString& text, QWidget* parent) 0558 : QFrame(parent) 0559 , d(new KMessageWidgetPrivate) 0560 { 0561 d->init(this); 0562 setText(text); 0563 } 0564 0565 KMessageWidget::KMessageWidget(QWidget* contentsWidget, QWidget* parent) 0566 : QFrame(parent) 0567 , d(new KMessageWidgetPrivate) 0568 { 0569 d->contentsWidget = contentsWidget; 0570 d->init(this); 0571 } 0572 0573 KMessageWidget::~KMessageWidget() 0574 { 0575 delete d; 0576 } 0577 0578 QString KMessageWidget::text() const 0579 { 0580 return d->textLabel ? d->textLabel->text() : QString(); 0581 } 0582 0583 void KMessageWidget::setText(const QString& text) 0584 { 0585 if (d->textLabel) { 0586 d->textLabel->setText(text); 0587 updateGeometry(); 0588 } 0589 } 0590 0591 KMessageWidget::MessageType KMessageWidget::messageType() const 0592 { 0593 return d->messageType; 0594 } 0595 0596 void KMessageWidget::setMessageType(KMessageWidget::MessageType type) 0597 { 0598 d->messageType = type; 0599 QIcon icon; 0600 d->colorSet = KColorScheme::View; 0601 switch (type) { 0602 case Positive: 0603 icon = koIcon("dialog-ok"); 0604 d->bgRole = KColorScheme::PositiveBackground; 0605 d->fgRole = KColorScheme::PositiveText; 0606 break; 0607 case Information: 0608 icon = koIcon("dialog-information"); 0609 d->bgRole = KColorScheme::NeutralBackground; 0610 d->fgRole = KColorScheme::NeutralText; 0611 break; 0612 case Warning: 0613 icon = koIcon("dialog-warning"); 0614 d->bgRole = KColorScheme::NeutralBackground; 0615 d->fgRole = KColorScheme::NeutralText; 0616 break; 0617 case Error: 0618 icon = koIcon("dialog-error"); 0619 d->bgRole = KColorScheme::NegativeBackground; 0620 d->fgRole = KColorScheme::NegativeText; 0621 break; 0622 } 0623 if (d->iconLabel) { 0624 const int size = KIconLoader::global()->currentSize(KIconLoader::MainToolbar); 0625 d->iconLabel->setPixmap(icon.pixmap(size)); 0626 } 0627 0628 d->updateStyleSheet(); 0629 d->updateLayout(); 0630 } 0631 0632 KMessageWidget::CalloutPointerDirection KMessageWidget::calloutPointerDirection() const 0633 { 0634 return d->content->calloutPointerDirection(); 0635 } 0636 0637 void KMessageWidget::setCalloutPointerDirection(KMessageWidget::CalloutPointerDirection direction) 0638 { 0639 d->content->setCalloutPointerDirection(direction); 0640 d->updateStyleSheet(); 0641 d->updateLayout(); 0642 d->content->updateCalloutPointerPosition(); 0643 } 0644 0645 QSize KMessageWidget::sizeHint() const 0646 { 0647 ensurePolished(); 0648 //qDebug() << "d->content->sizeHint():" << d->content->sizeHint(); 0649 //qDebug() << "QFrame::sizeHint():" << QFrame::sizeHint(); 0650 return QFrame::sizeHint(); 0651 /* QSize s1(QFrame::sizeHint()); 0652 QSize s2(d->content->sizeHint()); 0653 return QSize(qMax(s1.width(), s2.width()), qMax(s1.height(), s2.height()));*/ 0654 } 0655 0656 QSize KMessageWidget::minimumSizeHint() const 0657 { 0658 ensurePolished(); 0659 //qDebug() << "d->content->minimumSizeHint():" << d->content->minimumSizeHint(); 0660 //qDebug() << "QFrame::minimumSizeHint():" << QFrame::minimumSizeHint(); 0661 return QFrame::minimumSizeHint(); 0662 /* QSize s1(QFrame::minimumSizeHint()); 0663 QSize s2(d->content->minimumSizeHint()); 0664 return QSize(qMax(s1.width(), s2.width()), qMax(s1.height(), s2.height()));*/ 0665 } 0666 0667 bool KMessageWidget::event(QEvent* event) 0668 { 0669 if (event->type() == QEvent::Polish && !d->content->layout()) { 0670 d->createLayout(); 0671 } 0672 else if (event->type() == QEvent::Hide) { 0673 //qDebug() << "QEvent::Hide" << event->spontaneous(); 0674 if (!event->spontaneous()) { 0675 if (d->autoDelete) { 0676 deleteLater(); 0677 } 0678 } 0679 } 0680 else if (event->type() == QEvent::MouseButtonPress) { 0681 if (static_cast<QMouseEvent*>(event)->button() == Qt::LeftButton) { 0682 tryClickCloseMessage(); 0683 } 0684 } 0685 return QFrame::event(event); 0686 } 0687 0688 void KMessageWidget::resizeEvent(QResizeEvent* event) 0689 { 0690 QFrame::resizeEvent(event); 0691 if (d->timeLine->state() == QTimeLine::NotRunning) { 0692 d->content->resize(size()); 0693 d->updateStyleSheet(); // needed because margins could be changed 0694 } 0695 } 0696 0697 void KMessageWidget::paintEvent(QPaintEvent* event) 0698 { 0699 QFrame::paintEvent(event); 0700 if (d->timeLine->state() == QTimeLine::Running) { 0701 QPainter painter(this); 0702 painter.setOpacity(d->timeLine->currentValue() * d->timeLine->currentValue()); 0703 painter.drawPixmap(0, 0, d->contentSnapShot); 0704 } 0705 } 0706 0707 void KMessageWidget::showEvent(QShowEvent* event) 0708 { 0709 QFrame::showEvent(event); 0710 if (!event->spontaneous()) { 0711 #if 0 0712 int wantedHeight = d->content->sizeHint().height(); 0713 d->content->setGeometry(0, 0, width(), wantedHeight); 0714 if (d->buttons.isEmpty()) { 0715 setFixedHeight(wantedHeight); 0716 } 0717 #endif 0718 } 0719 } 0720 0721 bool KMessageWidget::wordWrap() const 0722 { 0723 return d->wordWrap; 0724 } 0725 0726 void KMessageWidget::setWordWrap(bool wordWrap) 0727 { 0728 d->wordWrap = wordWrap; 0729 if (d->textLabel) { 0730 d->textLabel->setWordWrap(wordWrap); 0731 d->updateLayout(); 0732 } 0733 } 0734 0735 bool KMessageWidget::isCloseButtonVisible() const 0736 { 0737 return d->closeButton->isVisible(); 0738 } 0739 0740 void KMessageWidget::setCloseButtonVisible(bool show) 0741 { 0742 d->closeButton->setVisible(show); 0743 } 0744 0745 bool KMessageWidget::clickClosesMessage() const 0746 { 0747 return d->clickClosesMessage; 0748 } 0749 0750 void KMessageWidget::setClickClosesMessage(bool set) 0751 { 0752 d->clickClosesMessage = set; 0753 } 0754 0755 void KMessageWidget::addAction(QAction* action) 0756 { 0757 QFrame::addAction(action); 0758 d->updateLayout(); 0759 } 0760 0761 void KMessageWidget::setDefaultAction(QAction* action) 0762 { 0763 d->defaultAction = action; 0764 d->createLayout(); 0765 } 0766 0767 void KMessageWidget::setButtonLeftAlignedForAction(QAction *action) 0768 { 0769 d->leftAlignedButtons.insert(action); 0770 } 0771 0772 void KMessageWidget::removeAction(QAction* action) 0773 { 0774 QFrame::removeAction(action); 0775 d->updateLayout(); 0776 } 0777 0778 void KMessageWidget::setAutoDelete(bool set) 0779 { 0780 d->autoDelete = set; 0781 } 0782 0783 void KMessageWidget::animatedShow() 0784 { 0785 if (!(KexiUtils::graphicEffectsLevel() & KexiUtils::SimpleAnimationEffects)) { 0786 show(); 0787 return; 0788 } 0789 0790 if (isVisible()) { 0791 return; 0792 } 0793 0794 d->content->updateCalloutPointerPosition(); 0795 QFrame::show(); 0796 if (d->contentsWidget) { 0797 int wantedHeight = height(); 0798 d->content->setGeometry(0, 0, width(), wantedHeight); 0799 setFixedHeight(wantedHeight); 0800 } 0801 else { 0802 setFixedHeight(0); 0803 int wantedHeight = d->content->sizeHint().height(); 0804 d->content->setGeometry(0, -wantedHeight, width(), wantedHeight); 0805 } 0806 0807 d->updateSnapShot(); 0808 0809 d->timeLine->setDirection(QTimeLine::Forward); 0810 if (d->timeLine->state() == QTimeLine::NotRunning) { 0811 d->timeLine->start(); 0812 } 0813 } 0814 0815 void KMessageWidget::animatedHide() 0816 { 0817 if (!(KexiUtils::graphicEffectsLevel() & KexiUtils::SimpleAnimationEffects)) { 0818 hide(); 0819 return; 0820 } 0821 0822 if (!isVisible()) { 0823 return; 0824 } 0825 0826 d->content->move(0, -d->content->height()); 0827 d->updateSnapShot(); 0828 0829 d->timeLine->setDirection(QTimeLine::Backward); 0830 if (d->timeLine->state() == QTimeLine::NotRunning) { 0831 d->timeLine->start(); 0832 } 0833 } 0834 0835 void KMessageWidget::setCalloutPointerPosition(const QPoint& globalPos) 0836 { 0837 d->content->setCalloutPointerPosition(globalPos); 0838 } 0839 0840 QPoint KMessageWidget::calloutPointerPosition() const 0841 { 0842 return d->content->calloutPointerPosition(); 0843 } 0844 0845 QBrush KMessageWidget::backgroundBrush() const 0846 { 0847 return d->content->bgBrush; 0848 } 0849 0850 QBrush KMessageWidget::borderBrush() const 0851 { 0852 return d->content->borderBrush; 0853 } 0854 0855 void KMessageWidget::resizeToContents() 0856 { 0857 // qDebug() << LAYOUT_SPACING + d->iconLabel->width() + LAYOUT_SPACING + d->textLabel->width() + LAYOUT_SPACING; 0858 // qDebug() << "sizeHint():" << sizeHint(); 0859 // qDebug() << "d->content->sizeHint():" << d->content->sizeHint(); 0860 d->resizeToContentsOnTimeLineFinished = true; // try to resize later too if animation in progress 0861 (void)sizeHint(); // to update d->content->sizeHint() 0862 setFixedSize(d->content->sizeHint()); 0863 } 0864 0865 void KMessageWidget::slotTimeLineChanged(qreal value) 0866 { 0867 if (!d->contentsWidget) { 0868 setFixedHeight(qMin(value * 2, qreal(1.0)) * d->content->height()); 0869 } 0870 update(); 0871 } 0872 0873 void KMessageWidget::slotTimeLineFinished() 0874 { 0875 if (d->timeLine->direction() == QTimeLine::Forward) { 0876 // Show 0877 d->content->move(0, 0); 0878 d->content->updateCalloutPointerPosition(); 0879 if (d->resizeToContentsOnTimeLineFinished) { 0880 d->resizeToContentsOnTimeLineFinished = false; 0881 d->content->resize(size()); 0882 d->updateStyleSheet(); // needed because margins could be changed 0883 } 0884 //q->setFixedHeight(QWIDGETSIZE_MAX); 0885 if (d->defaultButton) { 0886 d->defaultButton->setFocus(); 0887 } 0888 emit animatedShowFinished(); 0889 } else { 0890 // Hide 0891 hide(); 0892 emit animatedHideFinished(); 0893 } 0894 } 0895 0896 void KMessageWidget::tryClickCloseMessage() 0897 { 0898 if (d->clickClosesMessage) { 0899 QTimer::singleShot(100, this, SLOT(animatedHide())); 0900 } 0901 }