QML Google Suggest

From Qt Wiki
Jump to navigation Jump to search


This snippet article shows how to make a Google Suggest component to be used in conjunction with a TextInput element.

This is what it looks like:

gssnapshot.png

Implementation

// GoogleSuggest.qml
import QtQuick 1.1

Rectangle {
 id: googleSuggest
 property string textToSugget
 property string dsParam
 property bool timeToDie: false
 property int rowHeight: 30
 width: parent.width
 height: rowHeight*listView.count
 anchors.top: parent.bottom
 anchors.left: parent.left
 anchors.topMargin: 5

signal itemChoosen(string suggestion);

onTimeToDieChanged: googleSuggest.destroy();

XmlListModel {
 id: xmlModel
 source: "http://suggestqueries.google.com/complete/search?output=toolbar"+
 (dsParam!=="" ? "&ds="''dsParam : "")''
 "&q="+textToSugget

query: "/toplevel/CompleteSuggestion"

XmlRole { name: "suggestion"; query: "suggestion/@data/string()" }
 XmlRole { name: "num_queries"; query: "num_queries/@int/string()" }
 }

ListView {
 id: listView
 anchors.fill: parent
 cacheBuffer: 10
 highlight: Rectangle { color: Qt.rgba(0,0,1,0.3); radius: 8; z: listView.z+10 }
 highlightFollowsCurrentItem: true
 interactive: false
 currentIndex: -1

 model: xmlModel
 delegate: Rectangle {
 id: resultRow

 width: parent.width
 height: rowHeight
 color: (index % 2 === 0 ? "#ffffff" : "#eeeeff")
 border.color: "#000000"
 border.width: 1
 radius: 8

 Text {
 id: result
 anchors.verticalCenter: parent.verticalCenter
 anchors.left: parent.left
 anchors.leftMargin: 5
 anchors.right: numberOfResults.left
 anchors.rightMargin: 10
 font.pixelSize: 15
 font.bold: true
 text: suggestion
 clip: true
 }
 Text {
 id: numberOfResults
 anchors.verticalCenter: parent.verticalCenter
 anchors.right: parent.right
 anchors.rightMargin: 5
 font.pixelSize: 12
 font.italic: true
 text: num_queries
 }

 }

 MouseArea {
 anchors.fill: listView
 onMouseYChanged: {
 listView.currentIndex = Math.floor((mouseY+rowHeight) / rowHeight)- 1;
 }
 onReleased: {
 googleSuggest.itemChoosen(xmlModel.get(listView.currentIndex).suggestion);
 timeToDie = true;
 }
 }
 }
}

The functions below are used to dynamically load and unload the component. For example to pop up it when the user has entered at last 3 chars or unload it when TextInput.onAccepted signal is rised

// gs.js
var componentGS;
var objectGS;

// dsParam = "yt" only for YouTube suggest else it is empty
function popupGoogleSuggest ( callerItem, textString, dsParam ) {

deleteGoogleSuggest();
 componentGS = Qt.createComponent("GoogleSuggest.qml");
 objectGS = componentGS.createObject(callerItem);
 if (objectGS === null) {
 console.log("Error creating GoogleSuggest.qml", componentGS.errorString());
 } else {
 objectGS.textToSugget = textString;
 objectGS.dsParam = dsParam;
 }
 return objectGS;
}

function deleteGoogleSuggest()
{
 if (componentGS[[Image:==null && objectGS|==null && objectGS]]==undefined) {
 objectGS.timeToDie = true;
 }
}

Usage

import QtQuick 1.1
import "gs.js" as Functions

Rectangle {
 id: main
 width: 360
 height: 360

Rectangle {
 id: textContainer
 x: 0; y:0; width: 250; height: 30
 color: "#ffffff"
 border.color: "#000000"
 border.width: 1

TextInput {
 id: textInput
 property GoogleSuggest gsComponent
 anchors.centerIn: parent
 selectByMouse: true
 text: "write here"

// Used to prevent predictive text to pop up while typing in a TextInput
 // component. Else onTextChanged event isn't rised:
 // https://bugreports.qt.nokia.com/browse/QTBUG-22298
 inputMethodHints: Qt.ImhNoPredictiveText

function googleSuggest_item_choosen(text)
 {
 textInput.text=text;
 }

Timer {
 id: timerPopupGS
 running: false
 interval: 300
 repeat: false
 triggeredOnStart: false
 onTriggered: {
 if (textInput.focus && textInput.text !== "" && textInput.text.length > 2) {
 // Pop up GoogleSuggest and catch itemChoosen signal
 textInput.gsComponent = Functions.popupGoogleSuggest(textContainer, textInput.text, "");
 textInput.gsComponent.itemChoosen.connect(textInput.googleSuggest_item_choosen);
 }
 if (textInput.text.length<3) Functions.deleteGoogleSuggest();
 }
 }

onTextChanged: {
 timerPopupGS.restart();
 if (text.length<3) Functions.deleteGoogleSuggest();
 }
 onAccepted: {
 // eventually close VK
 closeSoftwareInputPanel();
 Functions.deleteGoogleSuggest();
 }
 onFocusChanged: {
 if (!focus) closeSoftwareInputPanel();
 if (!textInput.focus) {
 Functions.deleteGoogleSuggest();
 }
 }
 }

}
}