From 8d6d3d1894aab417837cabd3cc7723d3c9141a81 Mon Sep 17 00:00:00 2001 From: Gio Date: Thu, 15 Sep 2016 13:07:13 +0200 Subject: [PATCH] Retroshare QML App: Implemesh some basic stuff Implement location creation, selection and login Implement people listing Implement firends adding (not working yet) Depend on androidextra qt module only if compiling for android LibresapiLocalClient parse one line at time to avoid error if two requests are sent rapidly one after another LibresapiLocalClient socket path now is a parameter of openConnection() to use it as qml type constructor without parameter must be useful Added JSONListModel for JASON based MVC pattern --- .../src/retroshare-android-service.pro | 2 +- retroshare-android-service/src/service.cpp | 7 +- .../src/libresapilocalclient.cpp | 73 +++++---- retroshare-qml-app/src/libresapilocalclient.h | 46 +++--- retroshare-qml-app/src/main.cpp | 25 ++- retroshare-qml-app/src/qml.qrc | 6 +- retroshare-qml-app/src/qml/AddTrustedNode.qml | 39 +++++ retroshare-qml-app/src/qml/Contacts.qml | 56 +++++++ retroshare-qml-app/src/qml/JSONListModel.qml | 51 ++++++ .../src/qml/LibresapiLocalClientComm.qml | 5 - retroshare-qml-app/src/qml/Locations.qml | 152 ++++++++++++++++++ retroshare-qml-app/src/qml/jsonpath.js | 88 ++++++++++ retroshare-qml-app/src/qml/main.qml | 111 ++++++++++--- retroshare-qml-app/src/retroshare-qml-app.pro | 2 +- retroshare.pri | 1 + 15 files changed, 565 insertions(+), 99 deletions(-) create mode 100644 retroshare-qml-app/src/qml/AddTrustedNode.qml create mode 100644 retroshare-qml-app/src/qml/Contacts.qml create mode 100644 retroshare-qml-app/src/qml/JSONListModel.qml delete mode 100644 retroshare-qml-app/src/qml/LibresapiLocalClientComm.qml create mode 100644 retroshare-qml-app/src/qml/Locations.qml create mode 100644 retroshare-qml-app/src/qml/jsonpath.js diff --git a/retroshare-android-service/src/retroshare-android-service.pro b/retroshare-android-service/src/retroshare-android-service.pro index d327ace4f..bede07450 100644 --- a/retroshare-android-service/src/retroshare-android-service.pro +++ b/retroshare-android-service/src/retroshare-android-service.pro @@ -2,7 +2,7 @@ TARGET = retroshare-android-service -QT += core network androidextras +QT += core network QT -= gui CONFIG += c++11 diff --git a/retroshare-android-service/src/service.cpp b/retroshare-android-service/src/service.cpp index 5cea31e5f..9359af904 100644 --- a/retroshare-android-service/src/service.cpp +++ b/retroshare-android-service/src/service.cpp @@ -18,7 +18,10 @@ #include #include -#include + +#ifdef __ANDROID__ +# include +#endif #include "retroshare/rsinit.h" #include "api/ApiServer.h" @@ -39,8 +42,10 @@ int main(int argc, char *argv[]) qDebug() << "Listening on:" << sockPath; ApiServerLocal apiServerLocal(&api, sockPath); (void) apiServerLocal; +#ifdef __ANDROID__ qDebug() << "Is service.cpp running as a service?" << QtAndroid::androidService().isValid(); qDebug() << "Is service.cpp running as an activity?" << QtAndroid::androidActivity().isValid(); +#endif while (!ctrl_mod.processShouldExit()) { diff --git a/retroshare-qml-app/src/libresapilocalclient.cpp b/retroshare-qml-app/src/libresapilocalclient.cpp index 6b7e1d1f1..aa74feab7 100644 --- a/retroshare-qml-app/src/libresapilocalclient.cpp +++ b/retroshare-qml-app/src/libresapilocalclient.cpp @@ -1,35 +1,39 @@ +/* + * RetroShare Android QML App + * Copyright (C) 2016 Gioacchino Mazzurco + * Copyright (C) 2016 Manu Pineda + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + #include "libresapilocalclient.h" #include "debugutils.h" #include -/* Constructor de còpia per proves, no s'ha d'usar. -LibresapiLocalClient::LibresapiLocalClient(const LibresapiLocalClient & l) -{ - //mLocalSocket = l.mLocalSocket; - receivedBytes = l.receivedBytes; - json = l.json; -}*/ -LibresapiLocalClient::LibresapiLocalClient(const QString & socketPath) : - mLocalSocket(this) +void LibresapiLocalClient::openConnection(QString socketPath) { - myDebug(this); - mSocketPath = socketPath; - connect(& mLocalSocket, SIGNAL(error(QLocalSocket::LocalSocketError)), - this, SLOT(socketError(QLocalSocket::LocalSocketError))); - connect(& mLocalSocket, SIGNAL(readyRead()), - this, SLOT(read())); - //openConnection(); -} - - -void LibresapiLocalClient::openConnection() -{ - mLocalSocket.connectToServer(mSocketPath); + connect(& mLocalSocket, SIGNAL(error(QLocalSocket::LocalSocketError)), + this, SLOT(socketError(QLocalSocket::LocalSocketError))); + connect(& mLocalSocket, SIGNAL(readyRead()), + this, SLOT(read())); + mLocalSocket.connectToServer(socketPath); } int LibresapiLocalClient::request(const QString & path, const QString & jsonData) { + qDebug() << "LibresapiLocalClient::request()" << path << jsonData; QByteArray data; data.append(path); data.append('\n'); data.append(jsonData); data.append('\n'); @@ -38,25 +42,24 @@ int LibresapiLocalClient::request(const QString & path, const QString & jsonData return 1; } -void LibresapiLocalClient::socketError(QLocalSocket::LocalSocketError error) +void LibresapiLocalClient::socketError(QLocalSocket::LocalSocketError) { - myDebug("error!!!!\n" + mLocalSocket.errorString());//error.errorString()); + myDebug("error!!!!\n" + mLocalSocket.errorString()); } void LibresapiLocalClient::read() { - receivedBytes = mLocalSocket.readAll(); - - if(parseResponse()){ // pensar en fer un buffer per parsejar, per evitar errors. - emit goodResponseReceived(QString(receivedBytes)); - return; - } - - QString errMess = "The message was not understood!\n" - "It should be a JSON formatted text file\n" - "Its contents were:\n" + receivedBytes; - myDebug(errMess.replace(QChar('\n'), QChar::LineSeparator)); + receivedBytes = mLocalSocket.readLine(); + if(parseResponse()) // pensar en fer un buffer per parsejar, per evitar errors. + emit goodResponseReceived(QString(receivedBytes)); + else + { + QString errMess = "The message was not understood!\n" + "It should be a JSON formatted text file\n" + "Its contents were:\n" + receivedBytes; + myDebug(errMess.replace(QChar('\n'), QChar::LineSeparator)); + } } bool LibresapiLocalClient::parseResponse() diff --git a/retroshare-qml-app/src/libresapilocalclient.h b/retroshare-qml-app/src/libresapilocalclient.h index da2917359..cfbfb6dec 100644 --- a/retroshare-qml-app/src/libresapilocalclient.h +++ b/retroshare-qml-app/src/libresapilocalclient.h @@ -1,5 +1,6 @@ /* * libresapi local socket client + * Copyright (C) 2016 Gioacchino Mazzurco * Copyright (C) 2016 Manu Pineda * * This program is free software: you can redistribute it and/or modify @@ -26,39 +27,30 @@ class LibresapiLocalClient : public QObject { - Q_OBJECT + Q_OBJECT - public: +public: + LibresapiLocalClient() : mLocalSocket(this) {} - LibresapiLocalClient() {} - // LibresapiLocalClient(const LibresapiLocalClient & l); - LibresapiLocalClient(const QString & socketPath); - // potser abstreure el següent amb QUrl urlPath (path) i amb QJson jsonData. - Q_INVOKABLE int request(const QString & path, const QString & jsonData); - const QJsonDocument & getJson(); - Q_INVOKABLE void openConnection(); + // potser abstreure el següent amb QUrl urlPath (path) i amb QJson jsonData. + Q_INVOKABLE int request(const QString & path, const QString & jsonData); + const QJsonDocument & getJson(); + Q_INVOKABLE void openConnection(QString socketPath); - private: +private: + QLocalSocket mLocalSocket; + QByteArray receivedBytes; + QJsonDocument json; + //QVector responses; - QString mSocketPath; - QLocalSocket mLocalSocket; - QByteArray receivedBytes; - QJsonDocument json; - //QVector responses; + bool parseResponse(); //std::string msg); - bool parseResponse(); //std::string msg); - - private slots: - - void socketError(QLocalSocket::LocalSocketError error); - void read(); - - signals: - - void goodResponseReceived(const QString & msg);//, int requestId); - - public slots: +private slots: + void socketError(QLocalSocket::LocalSocketError error); + void read(); +signals: + void goodResponseReceived(const QString & msg);//, int requestId); }; #endif // LIBRESAPILOCALCLIENT_H diff --git a/retroshare-qml-app/src/main.cpp b/retroshare-qml-app/src/main.cpp index 05ada4369..1418ec3fb 100644 --- a/retroshare-qml-app/src/main.cpp +++ b/retroshare-qml-app/src/main.cpp @@ -22,7 +22,10 @@ #include #include -#include +#ifdef __ANDROID__ +# include +#endif + #include #include @@ -35,20 +38,28 @@ int main(int argc, char *argv[]) QGuiApplication app(argc, argv); QQmlApplicationEngine engine; + qmlRegisterType( + "org.retroshare.qml_components.LibresapiLocalClient", 1, 0, + "LibresapiLocalClient"); QString sockPath = QString::fromStdString(RsAccounts::ConfigDirectory()); sockPath.append("/libresapi.sock"); - LibresapiLocalClient llc(sockPath); - qmlRegisterType("LibresapiLocalClientQml", 1, 0, "LibresapiLocalClientComm"); - engine.rootContext()->setContextProperty("llc", &llc); - engine.load(QUrl(QLatin1String("qrc:/qml/main.qml"))); +#ifndef __ANDROID__ + sockPath = "/home/gio/.retroshare/LOC06_8730499b55bb946424d537b180bee10a/libresapi.sock"; +#endif - QFileInfo fileInfo(sockPath); + engine.rootContext()->setContextProperty("apiSocketPath", sockPath); + engine.load(QUrl(QLatin1String("qrc:/qml/main.qml"))); + QFileInfo fileInfo(sockPath); + +#ifdef __ANDROID__ qDebug() << "Is main.cpp running as a service?" << QtAndroid::androidService().isValid(); qDebug() << "Is main.cpp running as an activity?" << QtAndroid::androidActivity().isValid(); - qDebug() << "QML APP:" << sockPath << fileInfo.exists() << fileInfo.lastModified().toString(); +#endif + + qDebug() << "QML APP:" << sockPath << fileInfo.exists() << fileInfo.lastModified().toString(); return app.exec(); } diff --git a/retroshare-qml-app/src/qml.qrc b/retroshare-qml-app/src/qml.qrc index a0211e789..4bb111bc1 100644 --- a/retroshare-qml-app/src/qml.qrc +++ b/retroshare-qml-app/src/qml.qrc @@ -15,6 +15,10 @@ qml/ChannelGroupDelegate.qml qml/ApplicationBar.qml qml/AppButton.qml - qml/LibresapiLocalClientComm.qml + qml/Locations.qml + qml/jsonpath.js + qml/JSONListModel.qml + qml/Contacts.qml + qml/AddTrustedNode.qml diff --git a/retroshare-qml-app/src/qml/AddTrustedNode.qml b/retroshare-qml-app/src/qml/AddTrustedNode.qml new file mode 100644 index 000000000..80a0e094f --- /dev/null +++ b/retroshare-qml-app/src/qml/AddTrustedNode.qml @@ -0,0 +1,39 @@ +import QtQuick 2.0 +import QtQuick.Controls 1.4 +import QtQuick.Layouts 1.3 +import org.retroshare.qml_components.LibresapiLocalClient 1.0 + +Item +{ + Component.onCompleted: + { + rsApi.openConnection(apiSocketPath) + rsApi.request("/peers/self/certificate/", "") + } + + LibresapiLocalClient + { + id: rsApi + onGoodResponseReceived: myKeyField.text = JSON.parse(msg).data.cert_string + } + + ColumnLayout + { + anchors.top: parent.top + anchors.bottom: bottomButton.top + + TextField { id: myKeyField } + TextField { id: otherKeyField } + } + + Button + { + id: bottomButton + text: "Add trusted node" + anchors.bottom: parent.bottom + onClicked: + { + rsApi.request("/peers/examine_cert/", JSON.stringify({ cert_string: otherKeyField.text })) + } + } +} diff --git a/retroshare-qml-app/src/qml/Contacts.qml b/retroshare-qml-app/src/qml/Contacts.qml new file mode 100644 index 000000000..ef4fe3a13 --- /dev/null +++ b/retroshare-qml-app/src/qml/Contacts.qml @@ -0,0 +1,56 @@ +/* + * RetroShare Android QML App + * Copyright (C) 2016 Gioacchino Mazzurco + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import QtQuick 2.0 +import QtQuick.Controls 1.4 +import org.retroshare.qml_components.LibresapiLocalClient 1.0 + +Item +{ + function refreshData() + { + rsApi.openConnection(apiSocketPath) + rsApi.request("/identity/*/", "") + } + + Component.onCompleted: refreshData() + onFocusChanged: focus && refreshData() + + LibresapiLocalClient + { + id: rsApi + onGoodResponseReceived: locationsModel.json = msg + } + + JSONListModel + { + id: locationsModel + query: "$.data[*]" + } + + ListView + { + id: locationsListView + width: parent.width + height: 300 + model: locationsModel.model + delegate: Text { text: model.name } + } + + Text { text: "Contacts View"; anchors.bottom: parent.bottom } +} diff --git a/retroshare-qml-app/src/qml/JSONListModel.qml b/retroshare-qml-app/src/qml/JSONListModel.qml new file mode 100644 index 000000000..cee905d75 --- /dev/null +++ b/retroshare-qml-app/src/qml/JSONListModel.qml @@ -0,0 +1,51 @@ +/* JSONListModel - a QML ListModel with JSON and JSONPath support + * + * Copyright (c) 2012 Romain Pokrzywka (KDAB) (romain@kdab.com) + * Licensed under the MIT licence (http://opensource.org/licenses/mit-license.php) + */ + +import QtQuick 2.0 +import "jsonpath.js" as JSONPath + +Item { + property string source: "" + property string json: "" + property string query: "" + + property ListModel model : ListModel { id: jsonModel } + property alias count: jsonModel.count + + onSourceChanged: { + var xhr = new XMLHttpRequest; + xhr.open("GET", source); + xhr.onreadystatechange = function() { + if (xhr.readyState == XMLHttpRequest.DONE) + json = xhr.responseText; + } + xhr.send(); + } + + onJsonChanged: updateJSONModel() + onQueryChanged: updateJSONModel() + + function updateJSONModel() { + jsonModel.clear(); + + if ( json === "" ) + return; + + var objectArray = parseJSONString(json, query); + for ( var key in objectArray ) { + var jo = objectArray[key]; + jsonModel.append( jo ); + } + } + + function parseJSONString(jsonString, jsonPathQuery) { + var objectArray = JSON.parse(jsonString); + if ( jsonPathQuery !== "" ) + objectArray = JSONPath.jsonPath(objectArray, jsonPathQuery); + + return objectArray; + } +} diff --git a/retroshare-qml-app/src/qml/LibresapiLocalClientComm.qml b/retroshare-qml-app/src/qml/LibresapiLocalClientComm.qml deleted file mode 100644 index 75233c4ab..000000000 --- a/retroshare-qml-app/src/qml/LibresapiLocalClientComm.qml +++ /dev/null @@ -1,5 +0,0 @@ -import LibresapiLocalClientQml 1.0 - -LibresapiLocalClientComm { - id: llc -} diff --git a/retroshare-qml-app/src/qml/Locations.qml b/retroshare-qml-app/src/qml/Locations.qml new file mode 100644 index 000000000..3e3c5e62e --- /dev/null +++ b/retroshare-qml-app/src/qml/Locations.qml @@ -0,0 +1,152 @@ +/* + * RetroShare Android QML App + * Copyright (C) 2016 Gioacchino Mazzurco + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import QtQuick 2.0 +import QtQuick.Controls 1.4 +import QtQuick.Layouts 1.3 +import org.retroshare.qml_components.LibresapiLocalClient 1.0 + +Item +{ + id: locationView + state: "selectLocation" + + states: + [ + State + { + name: "selectLocation" + PropertyChanges { target: locationsListView; visible: true } + PropertyChanges { target: createLocationView; visible: false } + PropertyChanges + { + target: bottomButton + text: "Create new location" + onClicked: locationView.state = "createLocation" + } + }, + State + { + name: "createLocation" + PropertyChanges { target: locationsListView; visible: false } + PropertyChanges { target: createLocationView; visible: true } + PropertyChanges + { + target: bottomButton + text: "Save" + onClicked: + { + var jsonData = { pgp_name: nameField.text, ssl_name: nameField.text, pgp_password: passwordField.text } + rsApi.request("/control/create_location/", JSON.stringify(jsonData)) + onClicked: locationView.state = "savingLocation" + } + } + }, + State + { + name: "savingLocation" + PropertyChanges { target: locationsListView; visible: false } + PropertyChanges { target: createLocationView; color: "grey" } + PropertyChanges + { + target: bottomButton + text: "Saving..." + enabled: false + } + }, + State + { + name: "loggingIn" + PropertyChanges { target: locationsListView; visible: false } + PropertyChanges { target: createLocationView; visible: true } + PropertyChanges { target: nameField; enabled: false} + PropertyChanges + { + target: bottomButton + text: "Login" + enabled: true + onClicked: + { + var jsonData = { id: nameField.sslid, autologin: false } + rsApi.request("/control/login/", JSON.stringify(jsonData)) + jsonData = { password: passwordField.text } + rsApi.request("/control/password/", JSON.stringify(jsonData)) + } + } + } + ] + + Component.onCompleted: + { + rsApi.openConnection(apiSocketPath) + rsApi.request("/control/locations/", "") + } + + LibresapiLocalClient + { + id: rsApi + onGoodResponseReceived: locationsModel.json = msg + } + + JSONListModel + { + id: locationsModel + query: "$.data[*]" + } + + ListView + { + id: locationsListView + width: parent.width + anchors.top: parent.top + anchors.bottom: bottomButton.top + model: locationsModel.model + delegate: Button + { + text: model.name + property string sslid: model.id + onClicked: + { + locationView.state = "loggingIn" + nameField.text = text + } + } + visible: false + } + + ColumnLayout + { + id: createLocationView + width: parent.width + anchors.top: parent.top + anchors.bottom: bottomButton.top + visible: false + + Row { Text {text: "Name:" } TextField { id: nameField; property string sslid } } + Row { Text {text: "Password:" } TextField { id: passwordField; echoMode: PasswordEchoOnEdit } } + } + + Text { text: "Locations View"; anchors.bottom: bottomButton.top } + + Button + { + id: bottomButton + text: "Create new location" + anchors.bottom: parent.bottom + } +} diff --git a/retroshare-qml-app/src/qml/jsonpath.js b/retroshare-qml-app/src/qml/jsonpath.js new file mode 100644 index 000000000..2cb6bb07e --- /dev/null +++ b/retroshare-qml-app/src/qml/jsonpath.js @@ -0,0 +1,88 @@ +/* JSONPath 0.8.5 - XPath for JSON + * + * Copyright (c) 2007 Stefan Goessner (goessner.net) + * Licensed under the MIT (MIT-LICENSE.txt) licence. + * + */ +function jsonPath(obj, expr, arg) { + var P = { + resultType: arg && arg.resultType || "VALUE", + result: [], + normalize: function(expr) { + var subx = []; + return expr.replace(/[\['](\??\(.*?\))[\]']|\['(.*?)'\]/g, function($0,$1,$2){return "[#"+(subx.push($1||$2)-1)+"]";}) /* http://code.google.com/p/jsonpath/issues/detail?id=4 */ + .replace(/'?\.'?|\['?/g, ";") + .replace(/;;;|;;/g, ";..;") + .replace(/;$|'?\]|'$/g, "") + .replace(/#([0-9]+)/g, function($0,$1){return subx[$1];}); + }, + asPath: function(path) { + var x = path.split(";"), p = "$"; + for (var i=1,n=x.length; i + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ import QtQuick 2.2 -import QtQuick.Layouts 1.1 -import QtQuick.Controls 1.1 // millor fer servir 2.0 o més -import LibresapiLocalClientQml 1.0 +import QtQuick.Controls 2.0 +import org.retroshare.qml_components.LibresapiLocalClient 1.0 -ApplicationWindow { - visible: true - width: 640 - height: 480 - title: qsTr("RSChat") +ApplicationWindow +{ + id: mainWindow + visible: true + title: qsTr("RSChat") + Rectangle + { + id: mainView + anchors.fill: parent; + + states: + [ + State + { + name: "waiting_account_select"; + PropertyChanges { target: swipeView; currentIndex: 1 } + }, + State + { + name: "running_ok" + PropertyChanges { target: swipeView; currentIndex: 2 } + }, + State + { + name: "running_ok_no_full_control" + PropertyChanges { target: swipeView; currentIndex: 2 } + } + ] + + LibresapiLocalClient + { + onGoodResponseReceived: + { + var jsonReponse = JSON.parse(msg) + mainView.state = jsonReponse.data.runstate + } + Component.onCompleted: + { + openConnection(apiSocketPath) + request("/control/runstate/", "") + } + } + + SwipeView + { + id: swipeView + anchors.fill: parent + visible: true + currentIndex: 1 + + Locations + { + id: locationsView + visible: true + } + + AddTrustedNode + { + id: addTrustedNodeView + visible: true + } + + Contacts + { + id: contactsView + visible: true + } + } + } /* - LibresapiLocalClientComm{ - id: llc - onGoodResponseReceived: gxss.title = msg - - }*/ - onSceneGraphInitialized: llc.openConnection() + onSceneGraphInitialized: llc.openConnection() Rectangle { id: page @@ -154,7 +225,5 @@ ApplicationWindow { } } } + */ } - - - diff --git a/retroshare-qml-app/src/retroshare-qml-app.pro b/retroshare-qml-app/src/retroshare-qml-app.pro index b9c79f8ec..63e34a404 100644 --- a/retroshare-qml-app/src/retroshare-qml-app.pro +++ b/retroshare-qml-app/src/retroshare-qml-app.pro @@ -1,6 +1,6 @@ !include("../../retroshare.pri"): error("Could not include file ../../retroshare.pri") -QT += qml quick androidextras +QT += qml quick CONFIG += c++11 diff --git a/retroshare.pri b/retroshare.pri index 08bb84a7d..aaee2e406 100644 --- a/retroshare.pri +++ b/retroshare.pri @@ -52,6 +52,7 @@ unix { android-g++ { CONFIG *= no_libresapihttpserver no_sqlcipher upnp_libupnp CONFIG -= libresapihttpserver sqlcipher upnp_miniupnpc + QT *= androidextras DEFINES *= "fopen64=fopen" DEFINES *= "fseeko64=fseeko" DEFINES *= "ftello64=ftello"