diff options
Diffstat (limited to 'src/webenginewidgets/ui/messagebubblewidget.cpp')
-rw-r--r-- | src/webenginewidgets/ui/messagebubblewidget.cpp | 221 |
1 files changed, 221 insertions, 0 deletions
diff --git a/src/webenginewidgets/ui/messagebubblewidget.cpp b/src/webenginewidgets/ui/messagebubblewidget.cpp new file mode 100644 index 000000000..3465f4218 --- /dev/null +++ b/src/webenginewidgets/ui/messagebubblewidget.cpp @@ -0,0 +1,221 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "messagebubblewidget_p.h" + +#include "api/qwebengineview.h" + +#include <QBitmap> +#include <QHBoxLayout> +#include <QIcon> +#include <QLabel> +#include <QStyle> + +namespace QtWebEngineWidgetUI { + +Q_GLOBAL_STATIC(MessageBubbleWidget, bubbleInstance) + +void MessageBubbleWidget::showBubble(QWebEngineView *view, const QRect &anchor, const QString &mainText, const QString &subText) +{ + hideBubble(); + if (mainText.isEmpty()) + return; + + bubbleInstance->createBubble(anchor.size().width(), mainText, subText); + bubbleInstance->moveToAnchor(view, anchor); +} + +void MessageBubbleWidget::hideBubble() +{ + bubbleInstance->hide(); +} + +void MessageBubbleWidget::moveBubble(QWebEngineView *view, const QRect &anchor) +{ + bubbleInstance->moveToAnchor(view, anchor); +} + +MessageBubbleWidget::MessageBubbleWidget() + : QWidget(0, Qt::ToolTip) + , m_mainLabel(new QLabel) + , m_subLabel(new QLabel) +{ + QHBoxLayout *hLayout = new QHBoxLayout; + hLayout->setAlignment(Qt::AlignTop); + hLayout->setSizeConstraint(QLayout::SetFixedSize); + hLayout->setMargin(3); + + const int iconSize = 18; + QIcon si = style()->standardIcon(QStyle::SP_MessageBoxWarning); + + if (!si.isNull()) { + QLabel *iconLabel = new QLabel(this); + iconLabel->setPixmap(si.pixmap(iconSize, iconSize)); + iconLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + iconLabel->setMargin(2); + hLayout->addWidget(iconLabel, 0, Qt::AlignTop); + } + + QVBoxLayout *vLayout = new QVBoxLayout; + + m_mainLabel->installEventFilter(this); + m_mainLabel->setWordWrap(true); + m_mainLabel->setTextFormat(Qt::PlainText); + m_mainLabel->setAlignment(Qt::AlignTop | Qt::AlignLeft); + vLayout->addWidget(m_mainLabel.data()); + + QFont mainFont = m_mainLabel->font(); + mainFont.setPointSize(mainFont.pointSize() + 4); + m_mainLabel->setFont(mainFont); + + m_subLabel->installEventFilter(this); + m_subLabel->setWordWrap(true); + m_subLabel->setTextFormat(Qt::PlainText); + m_subLabel->setAlignment(Qt::AlignBottom | Qt::AlignLeft); + vLayout->addWidget(m_subLabel.data()); + + hLayout->addLayout(vLayout); + setLayout(hLayout); + + QPalette pal = palette(); + pal.setColor(QPalette::Window, QColor(0xff, 0xff, 0xe1)); + pal.setColor(QPalette::WindowText, Qt::black); + setPalette(pal); +} + +MessageBubbleWidget::~MessageBubbleWidget() +{ +} + +void MessageBubbleWidget::paintEvent(QPaintEvent *) +{ + QPainter painter(this); + painter.drawPixmap(rect(), m_pixmap); +} + +void MessageBubbleWidget::createBubble(const int maxWidth, const QString &mainText, const QString &subText) +{ + m_mainLabel->setText(mainText); + m_mainLabel->setMaximumWidth(maxWidth); + + m_subLabel->setText(subText); + m_subLabel->setMaximumWidth(maxWidth); + m_subLabel->setVisible(!subText.isEmpty()); + + int border = 1; + int arrowHeight = 18; + bool roundedCorners = true; + +#if defined(QT_NO_XSHAPE) && defined(Q_WS_X11) + // XShape is required for setting the mask, so we just + // draw an ugly square when its not available + arrowHeight = 0; + roundedCorners = false; +#endif + + setContentsMargins(border + 3, border + arrowHeight + 2, border + 3, border + 2); + show(); // The widget should be visible for updateGeometry() + updateGeometry(); + m_pixmap = QPixmap(sizeHint()); + + QPainterPath path = drawBoxPath(QPoint(0, arrowHeight), border, roundedCorners); + + // Draw border and set background + QPainter painter(&m_pixmap); + painter.setPen(QPen(palette().color(QPalette::Window).darker(160), border)); + painter.setBrush(palette().color(QPalette::Window)); + painter.drawPath(path); +} + +void MessageBubbleWidget::moveToAnchor(QWebEngineView *view, const QRect &anchor) +{ + QPoint topLeft = view->mapToGlobal(anchor.topLeft()); + move(topLeft.x(), topLeft.y() + anchor.height()); +} + +QPainterPath MessageBubbleWidget::drawBoxPath(const QPoint &pos, int border, bool roundedCorners) +{ + const int arrowHeight = pos.y(); + const int arrowOffset = 18; + const int arrowWidth = 18; + + const int cornerRadius = roundedCorners ? 7 : 0; + + const int messageBoxLeft = pos.x(); + const int messageBoxTop = arrowHeight; + const int messageBoxRight = m_pixmap.width() - 1; + const int messageBoxBottom = m_pixmap.height() - 1; + + QPainterPath path; + path.moveTo(messageBoxLeft + cornerRadius, messageBoxTop); + + if (arrowHeight) { + path.lineTo(messageBoxLeft + arrowOffset, messageBoxTop); + path.lineTo(messageBoxLeft + arrowOffset, messageBoxTop - arrowHeight); + path.lineTo(messageBoxLeft + arrowOffset + arrowWidth, messageBoxTop); + } + + if (roundedCorners) { + path.lineTo(messageBoxRight - cornerRadius, messageBoxTop); + path.quadTo(messageBoxRight, messageBoxTop, messageBoxRight, messageBoxTop + cornerRadius); + path.lineTo(messageBoxRight, messageBoxBottom - cornerRadius); + path.quadTo(messageBoxRight, messageBoxBottom, messageBoxRight - cornerRadius, messageBoxBottom); + path.lineTo(messageBoxLeft + cornerRadius, messageBoxBottom); + path.quadTo(messageBoxLeft, messageBoxBottom, messageBoxLeft, messageBoxBottom - cornerRadius); + path.lineTo(messageBoxLeft, messageBoxTop + cornerRadius); + path.quadTo(messageBoxLeft, messageBoxTop, messageBoxLeft + cornerRadius, messageBoxTop); + } else { + path.lineTo(messageBoxRight, messageBoxTop); + path.lineTo(messageBoxRight, messageBoxBottom); + path.lineTo(messageBoxLeft, messageBoxBottom); + path.moveTo(messageBoxLeft, messageBoxTop); + } + + // Set mask + if (arrowHeight || roundedCorners) { + QBitmap bitmap = QBitmap(sizeHint()); + bitmap.fill(Qt::color0); + QPainter painter(&bitmap); + painter.setPen(QPen(Qt::color1, border)); + painter.setBrush(QBrush(Qt::color1)); + painter.drawPath(path); + setMask(bitmap); + } + + return path; +} + +} // namespace QtWebEngineWidgetUI |