urllineedit.cpp Example File
webenginewidgets/demobrowser/urllineedit.cpp
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** 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 The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "urllineedit.h"
#include "browserapplication.h"
#include "searchlineedit.h"
#include "webview.h"
#include <QtCore/QEvent>
#include <QtCore/QMimeData>
#include <QtWidgets/QApplication>
#include <QtWidgets/QCompleter>
#include <QtGui/QFocusEvent>
#include <QtWidgets/QHBoxLayout>
#include <QtWidgets/QLabel>
#include <QtWidgets/QLineEdit>
#include <QtGui/QDrag>
#include <QtGui/QPainter>
#include <QtWidgets/QStyle>
#include <QtWidgets/QStyleOptionFrame>
#include <QtCore/QDebug>
ExLineEdit:: ExLineEdit(QWidget * parent)
: QWidget (parent)
, m_leftWidget(0 )
, m_lineEdit(new QLineEdit (this ))
, m_clearButton(0 )
{
setFocusPolicy(m_lineEdit- > focusPolicy());
setAttribute(Qt :: WA_InputMethodEnabled);
setSizePolicy(m_lineEdit- > sizePolicy());
setBackgroundRole(m_lineEdit- > backgroundRole());
setMouseTracking(true );
setAcceptDrops(true );
setAttribute(Qt :: WA_MacShowFocusRect, true );
QPalette p = m_lineEdit- > palette();
setPalette(p);
// line edit
m_lineEdit- > setFrame(false );
m_lineEdit- > setFocusProxy(this );
m_lineEdit- > setAttribute(Qt :: WA_MacShowFocusRect, false );
QPalette clearPalette = m_lineEdit- > palette();
clearPalette. setBrush(QPalette :: Base, QBrush (Qt :: transparent));
m_lineEdit- > setPalette(clearPalette);
// clearButton
m_clearButton = new ClearButton(this );
connect(m_clearButton, SIGNAL(clicked()),
m_lineEdit, SLOT(clear()));
connect(m_lineEdit, SIGNAL(textChanged(QString )),
m_clearButton, SLOT(textChanged(QString )));
}
void ExLineEdit:: setLeftWidget(QWidget * widget)
{
m_leftWidget = widget;
}
QWidget * ExLineEdit:: leftWidget() const
{
return m_leftWidget;
}
void ExLineEdit:: resizeEvent(QResizeEvent * event)
{
Q_ASSERT(m_leftWidget);
updateGeometries();
QWidget :: resizeEvent(event);
}
void ExLineEdit:: updateGeometries()
{
QStyleOptionFrame panel;
initStyleOption(& panel);
QRect rect = style()- > subElementRect(QStyle :: SE_LineEditContents, & panel, this );
int height = rect. height();
int width = rect. width();
int m_leftWidgetHeight = m_leftWidget- > height();
m_leftWidget- > setGeometry(rect. x() + 2 , rect. y() + (height - m_leftWidgetHeight)/ 2 ,
m_leftWidget- > width(), m_leftWidget- > height());
int clearButtonWidth = this - > height();
m_lineEdit- > setGeometry(m_leftWidget- > x() + m_leftWidget- > width(), 0 ,
width - clearButtonWidth - m_leftWidget- > width(), this - > height());
m_clearButton- > setGeometry(this - > width() - clearButtonWidth, 0 ,
clearButtonWidth, this - > height());
}
void ExLineEdit:: initStyleOption(QStyleOptionFrame * option) const
{
option- > initFrom(this );
option- > rect = contentsRect();
option- > lineWidth = style()- > pixelMetric(QStyle :: PM_DefaultFrameWidth, option, this );
option- > midLineWidth = 0 ;
option- > state | = QStyle :: State_Sunken;
if (m_lineEdit- > isReadOnly())
option- > state | = QStyle :: State_ReadOnly;
#ifdef QT_KEYPAD_NAVIGATION
if (hasEditFocus())
option- > state | = QStyle :: State_HasEditFocus;
#endif
option- > features = QStyleOptionFrame :: None;
}
QSize ExLineEdit:: sizeHint() const
{
m_lineEdit- > setFrame(true );
QSize size = m_lineEdit- > sizeHint();
m_lineEdit- > setFrame(false );
return size;
}
void ExLineEdit:: focusInEvent(QFocusEvent * event)
{
m_lineEdit- > event(event);
QWidget :: focusInEvent(event);
}
void ExLineEdit:: focusOutEvent(QFocusEvent * event)
{
m_lineEdit- > event(event);
if (m_lineEdit- > completer()) {
connect(m_lineEdit- > completer(), SIGNAL(activated(QString )),
m_lineEdit, SLOT(setText(QString )));
connect(m_lineEdit- > completer(), SIGNAL(highlighted(QString )),
m_lineEdit, SLOT(_q_completionHighlighted(QString )));
}
QWidget :: focusOutEvent(event);
}
void ExLineEdit:: keyPressEvent(QKeyEvent * event)
{
m_lineEdit- > event(event);
}
bool ExLineEdit:: event(QEvent * event)
{
if (event- > type() = = QEvent :: ShortcutOverride)
return m_lineEdit- > event(event);
return QWidget :: event(event);
}
void ExLineEdit:: paintEvent(QPaintEvent * )
{
QPainter p(this );
QStyleOptionFrame panel;
initStyleOption(& panel);
style()- > drawPrimitive(QStyle :: PE_PanelLineEdit, & panel, & p, this );
}
QVariant ExLineEdit:: inputMethodQuery(Qt :: InputMethodQuery property) const
{
return m_lineEdit- > inputMethodQuery(property);
}
void ExLineEdit:: inputMethodEvent(QInputMethodEvent * e)
{
m_lineEdit- > event(e);
}
class UrlIconLabel : public QLabel
{
public :
UrlIconLabel(QWidget * parent);
WebView * m_webView;
protected :
void mousePressEvent(QMouseEvent * event);
void mouseMoveEvent(QMouseEvent * event);
private :
QPoint m_dragStartPos;
};
UrlIconLabel:: UrlIconLabel(QWidget * parent)
: QLabel (parent)
, m_webView(0 )
{
setMinimumWidth(16 );
setMinimumHeight(16 );
}
void UrlIconLabel:: mousePressEvent(QMouseEvent * event)
{
if (event- > button() = = Qt :: LeftButton)
m_dragStartPos = event- > pos();
QLabel :: mousePressEvent(event);
}
void UrlIconLabel:: mouseMoveEvent(QMouseEvent * event)
{
if (event- > buttons() = = Qt :: LeftButton
& & (event- > pos() - m_dragStartPos). manhattanLength() > QApplication :: startDragDistance()
& & m_webView) {
QDrag * drag = new QDrag (this );
QMimeData * mimeData = new QMimeData ;
mimeData- > setText(QString :: fromUtf8(m_webView- > url(). toEncoded()));
QList < QUrl > urls;
urls. append(m_webView- > url());
mimeData- > setUrls(urls);
drag- > setMimeData(mimeData);
drag- > exec();
}
}
UrlLineEdit:: UrlLineEdit(QWidget * parent)
: ExLineEdit(parent)
, m_webView(0 )
, m_iconLabel(0 )
{
// icon
m_iconLabel = new UrlIconLabel(this );
m_iconLabel- > resize(16 , 16 );
setLeftWidget(m_iconLabel);
m_defaultBaseColor = palette(). color(QPalette :: Base);
}
void UrlLineEdit:: setWebView(WebView * webView)
{
Q_ASSERT(! m_webView);
m_webView = webView;
m_iconLabel- > m_webView = webView;
connect(webView, SIGNAL(urlChanged(QUrl )),
this , SLOT(webViewUrlChanged(QUrl )));
connect(webView, SIGNAL(iconChanged(QIcon )),
this , SLOT(webViewIconChanged(QIcon )));
connect(webView, SIGNAL(loadProgress(int )),
this , SLOT(update()));
}
void UrlLineEdit:: webViewUrlChanged(const QUrl & url)
{
m_lineEdit- > setText(QString :: fromUtf8(url. toEncoded()));
m_lineEdit- > setCursorPosition(0 );
}
void UrlLineEdit:: webViewIconChanged(const QIcon & icon)
{
Q_ASSERT(m_webView);
m_iconLabel- > setPixmap(icon. pixmap(16 , 16 ));
}
QLinearGradient UrlLineEdit:: generateGradient(const QColor & color) const
{
QLinearGradient gradient(0 , 0 , 0 , height());
gradient. setColorAt(0 , m_defaultBaseColor);
gradient. setColorAt(0.15 , color. lighter(120 ));
gradient. setColorAt(0.5 , color);
gradient. setColorAt(0.85 , color. lighter(120 ));
gradient. setColorAt(1 , m_defaultBaseColor);
return gradient;
}
void UrlLineEdit:: focusOutEvent(QFocusEvent * event)
{
if (m_lineEdit- > text(). isEmpty() & & m_webView)
m_lineEdit- > setText(QString :: fromUtf8(m_webView- > url(). toEncoded()));
ExLineEdit:: focusOutEvent(event);
}
void UrlLineEdit:: paintEvent(QPaintEvent * event)
{
QPalette p = palette();
if (m_webView & & m_webView- > url(). scheme() = = QLatin1String("https" )) {
QColor lightYellow(248 , 248 , 210 );
p. setBrush(QPalette :: Base, generateGradient(lightYellow));
} else {
p. setBrush(QPalette :: Base, m_defaultBaseColor);
}
setPalette(p);
ExLineEdit:: paintEvent(event);
QPainter painter(this );
QStyleOptionFrame panel;
initStyleOption(& panel);
QRect backgroundRect = style()- > subElementRect(QStyle :: SE_LineEditContents, & panel, this );
if (m_webView & & ! hasFocus()) {
int progress = m_webView- > progress();
QColor loadingColor = QColor (116 , 192 , 250 );
painter. setBrush(generateGradient(loadingColor));
painter. setPen(Qt :: transparent);
int mid = backgroundRect. width() / 100.0f * progress;
QRect progressRect(backgroundRect. x(), backgroundRect. y(), mid, backgroundRect. height());
painter. drawRect(progressRect);
}
}