1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the demonstration applications of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL21$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** $QT_END_LICENSE$
31 **
32 ****************************************************************************/
33
34 #include "urllineedit.h"
35
36 #include "browserapplication.h"
37 #include "searchlineedit.h"
38 #include "webview.h"
39
40 #include <QtCore/QEvent>
41 #include <QtCore/QMimeData>
42
43 #include <QtWidgets/QApplication>
44 #include <QtWidgets/QCompleter>
45 #include <QtGui/QFocusEvent>
46 #include <QtWidgets/QHBoxLayout>
47 #include <QtWidgets/QLabel>
48 #include <QtWidgets/QLineEdit>
49 #include <QtGui/QDrag>
50 #include <QtGui/QPainter>
51 #include <QtWidgets/QStyle>
52 #include <QtWidgets/QStyleOptionFrameV2>
53
54 #include <QtCore/QDebug>
55
ExLineEdit(QWidget * parent)56 ExLineEdit::ExLineEdit(QWidget *parent)
57 : QWidget(parent)
58 , m_leftWidget(0)
59 , m_lineEdit(new QLineEdit(this))
60 , m_clearButton(0)
61 {
62 setFocusPolicy(m_lineEdit->focusPolicy());
63 setAttribute(Qt::WA_InputMethodEnabled);
64 setSizePolicy(m_lineEdit->sizePolicy());
65 setBackgroundRole(m_lineEdit->backgroundRole());
66 setMouseTracking(true);
67 setAcceptDrops(true);
68 setAttribute(Qt::WA_MacShowFocusRect, true);
69 QPalette p = m_lineEdit->palette();
70 setPalette(p);
71
72 // line edit
73 m_lineEdit->setFrame(false);
74 m_lineEdit->setFocusProxy(this);
75 m_lineEdit->setAttribute(Qt::WA_MacShowFocusRect, false);
76 QPalette clearPalette = m_lineEdit->palette();
77 clearPalette.setBrush(QPalette::Base, QBrush(Qt::transparent));
78 m_lineEdit->setPalette(clearPalette);
79
80 // clearButton
81 m_clearButton = new ClearButton(this);
82 connect(m_clearButton, SIGNAL(clicked()),
83 m_lineEdit, SLOT(clear()));
84 connect(m_lineEdit, SIGNAL(textChanged(QString)),
85 m_clearButton, SLOT(textChanged(QString)));
86 }
87
setLeftWidget(QWidget * widget)88 void ExLineEdit::setLeftWidget(QWidget *widget)
89 {
90 m_leftWidget = widget;
91 }
92
leftWidget() const93 QWidget *ExLineEdit::leftWidget() const
94 {
95 return m_leftWidget;
96 }
97
resizeEvent(QResizeEvent * event)98 void ExLineEdit::resizeEvent(QResizeEvent *event)
99 {
100 Q_ASSERT(m_leftWidget);
101 updateGeometries();
102 QWidget::resizeEvent(event);
103 }
104
updateGeometries()105 void ExLineEdit::updateGeometries()
106 {
107 QStyleOptionFrameV2 panel;
108 initStyleOption(&panel);
109 QRect rect = style()->subElementRect(QStyle::SE_LineEditContents, &panel, this);
110
111 int height = rect.height();
112 int width = rect.width();
113
114 int m_leftWidgetHeight = m_leftWidget->height();
115 m_leftWidget->setGeometry(rect.x() + 2, rect.y() + (height - m_leftWidgetHeight)/2,
116 m_leftWidget->width(), m_leftWidget->height());
117
118 int clearButtonWidth = this->height();
119 m_lineEdit->setGeometry(m_leftWidget->x() + m_leftWidget->width(), 0,
120 width - clearButtonWidth - m_leftWidget->width(), this->height());
121
122 m_clearButton->setGeometry(this->width() - clearButtonWidth, 0,
123 clearButtonWidth, this->height());
124 }
125
initStyleOption(QStyleOptionFrameV2 * option) const126 void ExLineEdit::initStyleOption(QStyleOptionFrameV2 *option) const
127 {
128 option->initFrom(this);
129 option->rect = contentsRect();
130 option->lineWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth, option, this);
131 option->midLineWidth = 0;
132 option->state |= QStyle::State_Sunken;
133 if (m_lineEdit->isReadOnly())
134 option->state |= QStyle::State_ReadOnly;
135 #ifdef QT_KEYPAD_NAVIGATION
136 if (hasEditFocus())
137 option->state |= QStyle::State_HasEditFocus;
138 #endif
139 option->features = QStyleOptionFrameV2::None;
140 }
141
sizeHint() const142 QSize ExLineEdit::sizeHint() const
143 {
144 m_lineEdit->setFrame(true);
145 QSize size = m_lineEdit->sizeHint();
146 m_lineEdit->setFrame(false);
147 return size;
148 }
149
focusInEvent(QFocusEvent * event)150 void ExLineEdit::focusInEvent(QFocusEvent *event)
151 {
152 m_lineEdit->event(event);
153 QWidget::focusInEvent(event);
154 }
155
focusOutEvent(QFocusEvent * event)156 void ExLineEdit::focusOutEvent(QFocusEvent *event)
157 {
158 m_lineEdit->event(event);
159
160 if (m_lineEdit->completer()) {
161 connect(m_lineEdit->completer(), SIGNAL(activated(QString)),
162 m_lineEdit, SLOT(setText(QString)));
163 connect(m_lineEdit->completer(), SIGNAL(highlighted(QString)),
164 m_lineEdit, SLOT(_q_completionHighlighted(QString)));
165 }
166 QWidget::focusOutEvent(event);
167 }
168
keyPressEvent(QKeyEvent * event)169 void ExLineEdit::keyPressEvent(QKeyEvent *event)
170 {
171 m_lineEdit->event(event);
172 }
173
event(QEvent * event)174 bool ExLineEdit::event(QEvent *event)
175 {
176 if (event->type() == QEvent::ShortcutOverride)
177 return m_lineEdit->event(event);
178 return QWidget::event(event);
179 }
180
paintEvent(QPaintEvent *)181 void ExLineEdit::paintEvent(QPaintEvent *)
182 {
183 QPainter p(this);
184 QStyleOptionFrameV2 panel;
185 initStyleOption(&panel);
186 style()->drawPrimitive(QStyle::PE_PanelLineEdit, &panel, &p, this);
187 }
188
inputMethodQuery(Qt::InputMethodQuery property) const189 QVariant ExLineEdit::inputMethodQuery(Qt::InputMethodQuery property) const
190 {
191 return m_lineEdit->inputMethodQuery(property);
192 }
193
inputMethodEvent(QInputMethodEvent * e)194 void ExLineEdit::inputMethodEvent(QInputMethodEvent *e)
195 {
196 m_lineEdit->event(e);
197 }
198
199
200 class UrlIconLabel : public QLabel
201 {
202
203 public:
204 UrlIconLabel(QWidget *parent);
205
206 WebView *m_webView;
207
208 protected:
209 void mousePressEvent(QMouseEvent *event);
210 void mouseMoveEvent(QMouseEvent *event);
211
212 private:
213 QPoint m_dragStartPos;
214
215 };
216
UrlIconLabel(QWidget * parent)217 UrlIconLabel::UrlIconLabel(QWidget *parent)
218 : QLabel(parent)
219 , m_webView(0)
220 {
221 setMinimumWidth(16);
222 setMinimumHeight(16);
223 }
224
mousePressEvent(QMouseEvent * event)225 void UrlIconLabel::mousePressEvent(QMouseEvent *event)
226 {
227 if (event->button() == Qt::LeftButton)
228 m_dragStartPos = event->pos();
229 QLabel::mousePressEvent(event);
230 }
231
mouseMoveEvent(QMouseEvent * event)232 void UrlIconLabel::mouseMoveEvent(QMouseEvent *event)
233 {
234 if (event->buttons() == Qt::LeftButton
235 && (event->pos() - m_dragStartPos).manhattanLength() > QApplication::startDragDistance()
236 && m_webView) {
237 QDrag *drag = new QDrag(this);
238 QMimeData *mimeData = new QMimeData;
239 mimeData->setText(QString::fromUtf8(m_webView->url().toEncoded()));
240 QList<QUrl> urls;
241 urls.append(m_webView->url());
242 mimeData->setUrls(urls);
243 drag->setMimeData(mimeData);
244 drag->exec();
245 }
246 }
247
UrlLineEdit(QWidget * parent)248 UrlLineEdit::UrlLineEdit(QWidget *parent)
249 : ExLineEdit(parent)
250 , m_webView(0)
251 , m_iconLabel(0)
252 {
253 // icon
254 m_iconLabel = new UrlIconLabel(this);
255 m_iconLabel->resize(16, 16);
256 setLeftWidget(m_iconLabel);
257 m_defaultBaseColor = palette().color(QPalette::Base);
258
259 webViewIconChanged();
260 }
261
setWebView(WebView * webView)262 void UrlLineEdit::setWebView(WebView *webView)
263 {
264 Q_ASSERT(!m_webView);
265 m_webView = webView;
266 m_iconLabel->m_webView = webView;
267 connect(webView, SIGNAL(urlChanged(QUrl)),
268 this, SLOT(webViewUrlChanged(QUrl)));
269 connect(webView, SIGNAL(loadFinished(bool)),
270 this, SLOT(webViewIconChanged()));
271 connect(webView, SIGNAL(iconChanged()),
272 this, SLOT(webViewIconChanged()));
273 connect(webView, SIGNAL(loadProgress(int)),
274 this, SLOT(update()));
275 }
276
webViewUrlChanged(const QUrl & url)277 void UrlLineEdit::webViewUrlChanged(const QUrl &url)
278 {
279 m_lineEdit->setText(QString::fromUtf8(url.toEncoded()));
280 m_lineEdit->setCursorPosition(0);
281 }
282
webViewIconChanged()283 void UrlLineEdit::webViewIconChanged()
284 {
285 QUrl url = (m_webView) ? m_webView->url() : QUrl();
286 QIcon icon = BrowserApplication::instance()->icon(url);
287 QPixmap pixmap(icon.pixmap(16, 16));
288 m_iconLabel->setPixmap(pixmap);
289 }
290
generateGradient(const QColor & color) const291 QLinearGradient UrlLineEdit::generateGradient(const QColor &color) const
292 {
293 QLinearGradient gradient(0, 0, 0, height());
294 gradient.setColorAt(0, m_defaultBaseColor);
295 gradient.setColorAt(0.15, color.lighter(120));
296 gradient.setColorAt(0.5, color);
297 gradient.setColorAt(0.85, color.lighter(120));
298 gradient.setColorAt(1, m_defaultBaseColor);
299 return gradient;
300 }
301
focusOutEvent(QFocusEvent * event)302 void UrlLineEdit::focusOutEvent(QFocusEvent *event)
303 {
304 if (m_lineEdit->text().isEmpty() && m_webView)
305 m_lineEdit->setText(QString::fromUtf8(m_webView->url().toEncoded()));
306 ExLineEdit::focusOutEvent(event);
307 }
308
paintEvent(QPaintEvent * event)309 void UrlLineEdit::paintEvent(QPaintEvent *event)
310 {
311 QPalette p = palette();
312 if (m_webView && m_webView->url().scheme() == QLatin1String("https")) {
313 QColor lightYellow(248, 248, 210);
314 p.setBrush(QPalette::Base, generateGradient(lightYellow));
315 } else {
316 p.setBrush(QPalette::Base, m_defaultBaseColor);
317 }
318 setPalette(p);
319 ExLineEdit::paintEvent(event);
320
321 QPainter painter(this);
322 QStyleOptionFrameV2 panel;
323 initStyleOption(&panel);
324 QRect backgroundRect = style()->subElementRect(QStyle::SE_LineEditContents, &panel, this);
325 if (m_webView && !hasFocus()) {
326 int progress = m_webView->progress();
327 QColor loadingColor = QColor(116, 192, 250);
328 painter.setBrush(generateGradient(loadingColor));
329 painter.setPen(Qt::transparent);
330 int mid = backgroundRect.width() / 100 * progress;
331 QRect progressRect(backgroundRect.x(), backgroundRect.y(), mid, backgroundRect.height());
332 painter.drawRect(progressRect);
333 }
334 }
335