- Qt 5.5
- Qt Network
- Google Suggest Example
- googlesuggest.cpp Example File
- Qt 5.5.1 Reference Documentation

# googlesuggest.cpp Example File

googlesuggest/googlesuggest.cpp

    /****************************************************************************
    **
    ** Copyright (C) 2015 The Qt Company Ltd.
    ** Contact: http://www.qt.io/licensing/
    **
    ** This file is part of the examples of the Qt Toolkit.
    **
    ** $QT_BEGIN_LICENSE:BSD$
    ** 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 "googlesuggest.h"

    #define GSUGGEST_URL "http://google.com/complete/search?output=toolbar&q=%1"

    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, SIGNAL(itemClicked(QTreeWidgetItem*,int)),
                SLOT(doneCompletion()));

        timer = new QTimer(this);
        timer->setSingleShot(true);
        timer->setInterval(500);
        connect(timer, SIGNAL(timeout()), SLOT(autoSuggest()));
        connect(editor, SIGNAL(textEdited(QString)), timer, SLOT(start()));

        connect(&networkManager, SIGNAL(finished(QNetworkReply*)),
                this, SLOT(handleNetworkData(QNetworkReply*)));

    }

    GSuggestCompletion::~GSuggestCompletion()
    {
        delete popup;
    }

    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;

            case Qt::Key_Escape:
                editor->setFocus();
                popup->hide();
                consumed = true;

            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;
    }

    void GSuggestCompletion::showCompletion(const QStringList &choices)
    {

        if (choices.isEmpty())
            return;

        const QPalette &pal = editor->palette();
        QColor color = pal.color(QPalette::Disabled, QPalette::WindowText);

        popup->setUpdatesEnabled(false);
        popup->clear();
        for (int i = 0; i < choices.count(); ++i) {
            QTreeWidgetItem * item;
            item = new QTreeWidgetItem(popup);
            item->setText(0, choices[i]);
            item->setTextColor(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();
    }

    void GSuggestCompletion::doneCompletion()
    {
        timer->stop();
        popup->hide();
        editor->setFocus();
        QTreeWidgetItem *item = popup->currentItem();
        if (item) {
            editor->setText(item->text(0));
            QMetaObject::invokeMethod(editor, "returnPressed");
        }
    }

    void GSuggestCompletion::autoSuggest()
    {
        QString str = editor->text();
        QString url = QString(GSUGGEST_URL).arg(str);
        networkManager.get(QNetworkRequest(QString(url)));
    }

    void GSuggestCompletion::preventSuggest()
    {
        timer->stop();
    }

    void GSuggestCompletion::handleNetworkData(QNetworkReply *networkReply)
    {
        QUrl url = networkReply->url();
        if (!networkReply->error()) {
            QStringList choices;

            QByteArray response(networkReply->readAll());
            QXmlStreamReader xml(response);
            while (!xml.atEnd()) {
                xml.readNext();
                if (xml.tokenType() == QXmlStreamReader::StartElement)
                    if (xml.name() == "suggestion") {
                        QStringRef str = xml.attributes().value("data");
                        choices << str.toString();
                    }
            }

            showCompletion(choices);
        }

        networkReply->deleteLater();
    }