Delete googlesuggest
As a networking example it doesn't contribute much. But it has some interesting uses of widget/events Pick-to: 6.5 Change-Id: I194d32e6a304ae41819c20751e9f1ee1d9b5abdb Reviewed-by: Konrad Kujawa <konrad.kujawa@qt.io> Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io> Reviewed-by: Alex Blasche <alexander.blasche@qt.io>
This commit is contained in:
parent
c20336fe03
commit
2145341071
@ -16,7 +16,6 @@ if(TARGET Qt6::Widgets)
|
||||
qt_internal_add_example(http)
|
||||
qt_internal_add_example(loopback)
|
||||
qt_internal_add_example(threadedfortuneserver)
|
||||
qt_internal_add_example(googlesuggest)
|
||||
qt_internal_add_example(torrent)
|
||||
qt_internal_add_example(multicastreceiver)
|
||||
qt_internal_add_example(multicastsender)
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 21 KiB |
@ -1,153 +0,0 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
|
||||
|
||||
/*!
|
||||
\example googlesuggest
|
||||
\title Google Suggest Example
|
||||
\ingroup examples-network
|
||||
\brief Obtains the list of search recommendations by the Google search engine.
|
||||
|
||||
The example uses the QNetworkAccessManager to obtain the list of search
|
||||
recommendations by Google as the user types into a QLineEdit.
|
||||
|
||||
\image googlesuggest-example.png
|
||||
|
||||
The application makes use of the \c get function in
|
||||
QNetworkAccessManager to post a request and obtain the result of the search
|
||||
query sent to the Google search engine. The results returned are listed as
|
||||
clickable links appearing below the search box as a drop-down menu.
|
||||
|
||||
The widget is built up by a QLineEdit as the search box, and a QTreeView
|
||||
used as a popup menu below the search box.
|
||||
|
||||
\section1 GSuggestCompletion Class Declaration
|
||||
|
||||
This class implements an event filter and a number of functions to display
|
||||
the search results and to determent when and how to perform the search.
|
||||
|
||||
\snippet googlesuggest/googlesuggest.h 1
|
||||
|
||||
The class connects to a QLineEdit and uses a QTreeWidget to display the
|
||||
results. A QTimer controls the start of the network requests that are
|
||||
executed using a QNetworkAccessManager.
|
||||
|
||||
\section1 GSuggestCompletion Class Implementation
|
||||
|
||||
We start by defining a constant containing the URL to be used in the Google
|
||||
queries. This is the basis for the query. The letters typed into the search
|
||||
box will be added to the query to perform the search itself.
|
||||
|
||||
\snippet googlesuggest/googlesuggest.cpp 1
|
||||
|
||||
In the constructor, we set the parent of this GSuggestCompletion instance
|
||||
to be the QLineEdit passed in. For simplicity, the QLineEdit is also stored
|
||||
in the explicit \c editor member variable.
|
||||
|
||||
We then create a QTreeWidget as a toplevel widget and configure the various
|
||||
properties to give it the look of a popup widget. The widget is populated
|
||||
with the results by Google Suggest API request.
|
||||
|
||||
Furthermore, we install the GSuggestCompletion instance as an event filter
|
||||
on the QTreeWidget, and connect the \c itemClicked() signal with the \c
|
||||
doneCompletion() slot.
|
||||
|
||||
A single-shot QTimer is used to start the request when the user has stopped
|
||||
typing for 500 ms.
|
||||
|
||||
Finally, we connect the networkManagers \c finished() signal with the \c
|
||||
handleNetworkData() slot to handle the incoming data.
|
||||
|
||||
\snippet googlesuggest/googlesuggest.cpp 2
|
||||
|
||||
Since the QTreeWidget popup has been instantiated as a toplevel widget, the
|
||||
destructor has to delete it explicitly from memory to avoid a memory leak.
|
||||
|
||||
\snippet googlesuggest/googlesuggest.cpp 3
|
||||
|
||||
The event filter handles mouse press and key press events that are
|
||||
delivered to the popup. For mouse press events we just hide the popup and
|
||||
return focus to the editor widget, and then return true to prevent further
|
||||
event processing.
|
||||
|
||||
Key event handling is implemented so that Enter and Return execute the
|
||||
selected link, while the Escape key hides the popup. Since we want to be
|
||||
able to navigate the list of suggestions using the different navigation
|
||||
keys on the keyboard we let Qt continue regular event processing for those
|
||||
by returning false from the eventFilter reimplementation.
|
||||
|
||||
For all other keys, the event will be passed on to the editor widget and the
|
||||
popup is hidden. This way the user's typing will not be interrupted by the
|
||||
popping up of the completion list.
|
||||
|
||||
\snippet googlesuggest/googlesuggest.cpp 4
|
||||
|
||||
The \c showCompletion() function populates the QTreeWidget with the results
|
||||
returned from the query. It takes a QStringList of the suggested search
|
||||
terms.
|
||||
|
||||
\snippet googlesuggest/googlesuggest.cpp 5
|
||||
|
||||
A QTreeWidgetItem is created for each index in the list and inserted into
|
||||
the QTreeWidget. Finally, we adjust position and size of the popup to make
|
||||
sure that it pops up in the correct position below the editor, and show it.
|
||||
|
||||
The \c doneCompletion() function, which is called by the event filter when
|
||||
either Enter or Return keys are pressed, stops the timer to prevent further
|
||||
requests and passes the text of the selected item to the editor. We then
|
||||
make the \c editor QLineEdit emit the returnPressed() signal, to which the
|
||||
application can connect to open the respective web page.
|
||||
|
||||
\snippet googlesuggest/googlesuggest.cpp 6
|
||||
|
||||
The \c autoSuggest() slot is called when the timer times out, and uses the
|
||||
text in the editor to build the complete search query. The query is then
|
||||
passed to the QNetworkAccessManager's \c get() function to start the
|
||||
request.
|
||||
|
||||
\snippet googlesuggest/googlesuggest.cpp 7
|
||||
|
||||
The function \c preventSuggest() stops the timer to prevent further
|
||||
requests from being started.
|
||||
|
||||
\snippet googlesuggest/googlesuggest.cpp 8
|
||||
|
||||
When the network request is finished, the QNetworkAccessManager delivers the
|
||||
data received from the server through the networkReply object.
|
||||
|
||||
\snippet googlesuggest/googlesuggest.cpp 9
|
||||
|
||||
To extract the data from the reply we use the \c readAll() function, which
|
||||
is inherited from QIODevice and returns a QByteArray. Since this data is
|
||||
encoded in XML we can use a QXmlStreamReader to traverse the data and
|
||||
extract the search result as QStrings, which we can stream into two
|
||||
QStringLists used to populate the popup.
|
||||
|
||||
Finally, we schedule the QNetworkReply object for deletion using the \c
|
||||
deleteLater function.
|
||||
|
||||
\section1 SearchBox Class Declaration
|
||||
|
||||
The SearchBox class inherits QLineEdit and adds the protected slot \c
|
||||
doSearch().
|
||||
|
||||
A \c GSuggestCompletion member provides the SearchBox with the request
|
||||
functionality and the suggestions returned from the Google search engine.
|
||||
|
||||
\snippet googlesuggest/searchbox.h 1
|
||||
|
||||
\section1 SearchBox Class Implementation
|
||||
|
||||
The search box constructor instantiates the GSuggestCompletion object and
|
||||
connects the returnPressed() signal to the doSearch() slot.
|
||||
|
||||
\snippet googlesuggest/searchbox.cpp 1
|
||||
|
||||
The function \c doSearch() stops the completer from sending any further
|
||||
queries to the search engine.
|
||||
|
||||
Further, the function extracts the selected search phrase and opens it
|
||||
in the default web browser using QDesktopServices.
|
||||
|
||||
\snippet googlesuggest/searchbox.cpp 2
|
||||
|
||||
*/
|
@ -1,39 +0,0 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
project(googlesuggest LANGUAGES CXX)
|
||||
|
||||
if(NOT DEFINED INSTALL_EXAMPLESDIR)
|
||||
set(INSTALL_EXAMPLESDIR "examples")
|
||||
endif()
|
||||
|
||||
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/network/googlesuggest")
|
||||
|
||||
find_package(Qt6 REQUIRED COMPONENTS Core Gui Network Widgets)
|
||||
|
||||
qt_standard_project_setup()
|
||||
|
||||
qt_add_executable(googlesuggest
|
||||
googlesuggest.cpp googlesuggest.h
|
||||
main.cpp
|
||||
searchbox.cpp searchbox.h
|
||||
)
|
||||
|
||||
set_target_properties(googlesuggest PROPERTIES
|
||||
WIN32_EXECUTABLE TRUE
|
||||
MACOSX_BUNDLE TRUE
|
||||
)
|
||||
|
||||
target_link_libraries(googlesuggest PRIVATE
|
||||
Qt6::Core
|
||||
Qt6::Gui
|
||||
Qt6::Network
|
||||
Qt6::Widgets
|
||||
)
|
||||
|
||||
install(TARGETS googlesuggest
|
||||
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
)
|
@ -1,184 +0,0 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include "googlesuggest.h"
|
||||
|
||||
//! [1]
|
||||
const QString gsuggestUrl(QStringLiteral("http://google.com/complete/search?output=toolbar&q=%1"));
|
||||
//! [1]
|
||||
|
||||
//! [2]
|
||||
GSuggestCompletion::GSuggestCompletion(QLineEdit *parent): QObject(parent), editor(parent)
|
||||
{
|
||||
popup = new QTreeWidget;
|
||||
popup->setWindowFlags(Qt::Popup);
|
||||
popup->setFocusPolicy(Qt::NoFocus);
|
||||
popup->setFocusProxy(parent);
|
||||
popup->setMouseTracking(true);
|
||||
|
||||
popup->setColumnCount(1);
|
||||
popup->setUniformRowHeights(true);
|
||||
popup->setRootIsDecorated(false);
|
||||
popup->setEditTriggers(QTreeWidget::NoEditTriggers);
|
||||
popup->setSelectionBehavior(QTreeWidget::SelectRows);
|
||||
popup->setFrameStyle(QFrame::Box | QFrame::Plain);
|
||||
popup->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
popup->header()->hide();
|
||||
|
||||
popup->installEventFilter(this);
|
||||
|
||||
connect(popup, &QTreeWidget::itemClicked,
|
||||
this, &GSuggestCompletion::doneCompletion);
|
||||
|
||||
timer.setSingleShot(true);
|
||||
timer.setInterval(500);
|
||||
connect(&timer, &QTimer::timeout,
|
||||
this, &GSuggestCompletion::autoSuggest);
|
||||
connect(editor, &QLineEdit::textEdited,
|
||||
&timer, QOverload<>::of(&QTimer::start));
|
||||
|
||||
connect(&networkManager, &QNetworkAccessManager::finished,
|
||||
this, &GSuggestCompletion::handleNetworkData);
|
||||
|
||||
}
|
||||
//! [2]
|
||||
|
||||
//! [3]
|
||||
GSuggestCompletion::~GSuggestCompletion()
|
||||
{
|
||||
delete popup;
|
||||
}
|
||||
//! [3]
|
||||
|
||||
//! [4]
|
||||
bool GSuggestCompletion::eventFilter(QObject *obj, QEvent *ev)
|
||||
{
|
||||
if (obj != popup)
|
||||
return false;
|
||||
|
||||
if (ev->type() == QEvent::MouseButtonPress) {
|
||||
popup->hide();
|
||||
editor->setFocus();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ev->type() == QEvent::KeyPress) {
|
||||
bool consumed = false;
|
||||
int key = static_cast<QKeyEvent*>(ev)->key();
|
||||
switch (key) {
|
||||
case Qt::Key_Enter:
|
||||
case Qt::Key_Return:
|
||||
doneCompletion();
|
||||
consumed = true;
|
||||
break;
|
||||
|
||||
case Qt::Key_Escape:
|
||||
editor->setFocus();
|
||||
popup->hide();
|
||||
consumed = true;
|
||||
break;
|
||||
|
||||
case Qt::Key_Up:
|
||||
case Qt::Key_Down:
|
||||
case Qt::Key_Home:
|
||||
case Qt::Key_End:
|
||||
case Qt::Key_PageUp:
|
||||
case Qt::Key_PageDown:
|
||||
break;
|
||||
|
||||
default:
|
||||
editor->setFocus();
|
||||
editor->event(ev);
|
||||
popup->hide();
|
||||
break;
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
//! [4]
|
||||
|
||||
//! [5]
|
||||
void GSuggestCompletion::showCompletion(const QList<QString> &choices)
|
||||
{
|
||||
if (choices.isEmpty())
|
||||
return;
|
||||
|
||||
const QPalette &pal = editor->palette();
|
||||
QColor color = pal.color(QPalette::Disabled, QPalette::WindowText);
|
||||
|
||||
popup->setUpdatesEnabled(false);
|
||||
popup->clear();
|
||||
|
||||
for (const auto &choice : choices) {
|
||||
auto item = new QTreeWidgetItem(popup);
|
||||
item->setText(0, choice);
|
||||
item->setForeground(0, color);
|
||||
}
|
||||
|
||||
popup->setCurrentItem(popup->topLevelItem(0));
|
||||
popup->resizeColumnToContents(0);
|
||||
popup->setUpdatesEnabled(true);
|
||||
|
||||
popup->move(editor->mapToGlobal(QPoint(0, editor->height())));
|
||||
popup->setFocus();
|
||||
popup->show();
|
||||
}
|
||||
//! [5]
|
||||
|
||||
//! [6]
|
||||
void GSuggestCompletion::doneCompletion()
|
||||
{
|
||||
timer.stop();
|
||||
popup->hide();
|
||||
editor->setFocus();
|
||||
QTreeWidgetItem *item = popup->currentItem();
|
||||
if (item) {
|
||||
editor->setText(item->text(0));
|
||||
QMetaObject::invokeMethod(editor, "returnPressed");
|
||||
}
|
||||
}
|
||||
//! [6]
|
||||
|
||||
//! [7]
|
||||
void GSuggestCompletion::autoSuggest()
|
||||
{
|
||||
QString str = editor->text();
|
||||
QString url = gsuggestUrl.arg(str);
|
||||
networkManager.get(QNetworkRequest(url));
|
||||
}
|
||||
//! [7]
|
||||
|
||||
//! [8]
|
||||
void GSuggestCompletion::preventSuggest()
|
||||
{
|
||||
timer.stop();
|
||||
}
|
||||
//! [8]
|
||||
|
||||
//! [9]
|
||||
void GSuggestCompletion::handleNetworkData(QNetworkReply *networkReply)
|
||||
{
|
||||
QUrl url = networkReply->url();
|
||||
if (networkReply->error() == QNetworkReply::NoError) {
|
||||
QList<QString> choices;
|
||||
|
||||
QByteArray response(networkReply->readAll());
|
||||
QXmlStreamReader xml(response);
|
||||
while (!xml.atEnd()) {
|
||||
xml.readNext();
|
||||
if (xml.tokenType() == QXmlStreamReader::StartElement)
|
||||
if (xml.name() == u"suggestion") {
|
||||
auto str = xml.attributes().value("data");
|
||||
choices << str.toString();
|
||||
}
|
||||
}
|
||||
|
||||
showCompletion(choices);
|
||||
}
|
||||
|
||||
networkReply->deleteLater();
|
||||
}
|
||||
//! [9]
|
@ -1,37 +0,0 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#ifndef GOOGLESUGGEST_H
|
||||
#define GOOGLESUGGEST_H
|
||||
|
||||
#include <QtWidgets>
|
||||
#include <QtNetwork>
|
||||
#include <QtCore>
|
||||
|
||||
//! [1]
|
||||
class GSuggestCompletion : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit GSuggestCompletion(QLineEdit *parent = nullptr);
|
||||
~GSuggestCompletion();
|
||||
bool eventFilter(QObject *obj, QEvent *ev) override;
|
||||
void showCompletion(const QList<QString> &choices);
|
||||
|
||||
public slots:
|
||||
|
||||
void doneCompletion();
|
||||
void preventSuggest();
|
||||
void autoSuggest();
|
||||
void handleNetworkData(QNetworkReply *networkReply);
|
||||
|
||||
private:
|
||||
QLineEdit *editor = nullptr;
|
||||
QTreeWidget *popup = nullptr;
|
||||
QTimer timer;
|
||||
QNetworkAccessManager networkManager;
|
||||
};
|
||||
//! [1]
|
||||
#endif // GOOGLESUGGEST_H
|
||||
|
@ -1,8 +0,0 @@
|
||||
QT += network widgets
|
||||
requires(qtConfig(itemviews))
|
||||
SOURCES = main.cpp searchbox.cpp googlesuggest.cpp
|
||||
HEADERS = searchbox.h googlesuggest.h
|
||||
|
||||
# install
|
||||
target.path = $$[QT_INSTALL_EXAMPLES]/network/googlesuggest
|
||||
INSTALLS += target
|
@ -1,14 +0,0 @@
|
||||
// Copyright (C) 2017 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include <QApplication>
|
||||
|
||||
#include "searchbox.h"
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
QApplication app(argc, argv);
|
||||
SearchBox searchEdit;
|
||||
searchEdit.show();
|
||||
return app.exec();
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
// Copyright (C) 2017 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include <QDesktopServices>
|
||||
#include <QUrl>
|
||||
|
||||
#include "searchbox.h"
|
||||
#include "googlesuggest.h"
|
||||
|
||||
const QString gsearchUrl = QStringLiteral("http://www.google.com/search?q=%1");
|
||||
|
||||
//! [1]
|
||||
SearchBox::SearchBox(QWidget *parent)
|
||||
: QLineEdit(parent)
|
||||
, completer(new GSuggestCompletion(this))
|
||||
{
|
||||
connect(this, &SearchBox::returnPressed, this, &SearchBox::doSearch);
|
||||
|
||||
setWindowTitle("Search with Google");
|
||||
|
||||
adjustSize();
|
||||
resize(400, height());
|
||||
setFocus();
|
||||
}
|
||||
//! [1]
|
||||
|
||||
//! [2]
|
||||
void SearchBox::doSearch()
|
||||
{
|
||||
completer->preventSuggest();
|
||||
QString url = gsearchUrl.arg(text());
|
||||
QDesktopServices::openUrl(url);
|
||||
}
|
||||
//! [2]
|
||||
|
@ -1,28 +0,0 @@
|
||||
// Copyright (C) 2017 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#ifndef SEARCHBOX_H
|
||||
#define SEARCHBOX_H
|
||||
|
||||
//! [1]
|
||||
#include <QLineEdit>
|
||||
|
||||
class GSuggestCompletion;
|
||||
|
||||
class SearchBox: public QLineEdit
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SearchBox(QWidget *parent = nullptr);
|
||||
|
||||
protected slots:
|
||||
void doSearch();
|
||||
|
||||
private:
|
||||
GSuggestCompletion *completer = nullptr;
|
||||
//! [1]
|
||||
};
|
||||
|
||||
|
||||
#endif // SEARCHBOX_H
|
@ -14,7 +14,6 @@ qtHaveModule(widgets) {
|
||||
http \
|
||||
loopback \
|
||||
threadedfortuneserver \
|
||||
googlesuggest \
|
||||
torrent \
|
||||
multicastreceiver \
|
||||
multicastsender
|
||||
|
@ -31,7 +31,6 @@
|
||||
\li \l{network/loopback}{Loopback}
|
||||
\li \l{network/threadedfortuneserver}{Threaded Fortune Server}\raisedaster
|
||||
\li \l{network/torrent}{Torrent}
|
||||
\li \l{network/googlesuggest}{Google Suggest}
|
||||
\li \l{network/bearercloud}{Bearer Cloud}\raisedaster
|
||||
\li \l{network/bearermonitor}{Bearer Monitor}
|
||||
\li \l{network/securesocketclient}{Secure Socket Client}
|
||||
|
Loading…
Reference in New Issue
Block a user