mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-10-01 02:35:48 -04:00
Merge branch 'qml_app_avatar_picker' into GSoC2017-evaluation-II
This commit is contained in:
commit
5f0cb3ce5d
@ -27,6 +27,45 @@ Item
|
||||
id: cntDt
|
||||
property var md
|
||||
property bool is_contact: cntDt.md.is_contact
|
||||
property bool isOwn: cntDt.md.own
|
||||
|
||||
Button
|
||||
{
|
||||
id: avatarPicker
|
||||
|
||||
text: "Change your Avatar"
|
||||
visible: isOwn
|
||||
|
||||
anchors.top: parent.top
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
onClicked:
|
||||
{
|
||||
fileChooser.open()
|
||||
}
|
||||
CustomFileChooser
|
||||
{
|
||||
id: fileChooser
|
||||
onResultFileChanged:
|
||||
{
|
||||
console.log("Result file changed! " , resultFile)
|
||||
|
||||
var base64Image = androidImagePicker.imageToBase64(resultFile)
|
||||
|
||||
rsApi.request("/identity/set_avatar", JSON.stringify({"gxs_id": cntDt.md.gxs_id, "avatar": base64Image }),
|
||||
function (par)
|
||||
{
|
||||
var jP = JSON.parse(par.response)
|
||||
if (jP.returncode === "ok")
|
||||
{
|
||||
console.log("Avatar changed! ")
|
||||
topFace.getDetails()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
AvatarOrColorHash
|
||||
{
|
||||
@ -34,7 +73,7 @@ Item
|
||||
|
||||
gxs_id: cntDt.md.gxs_id
|
||||
|
||||
anchors.top: parent.top
|
||||
anchors.top: (isOwn)? avatarPicker.bottom : parent.top
|
||||
anchors.topMargin: 6
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
|
@ -207,4 +207,8 @@
|
||||
|
||||
<!-- Added by G10h4ck: Needed permission for autostart at boot -->
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
|
||||
<!-- Added by Angesoc: used to pick images from gallery or take it from camera -->
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
||||
|
||||
</manifest>
|
||||
|
@ -19,17 +19,25 @@
|
||||
package org.retroshare.android.qml_app;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.database.Cursor;
|
||||
import android.os.Bundle;
|
||||
import android.provider.MediaStore;
|
||||
import android.util.Log;
|
||||
|
||||
import android.net.Uri;
|
||||
|
||||
import org.qtproject.qt5.android.bindings.QtActivity;
|
||||
|
||||
import org.retroshare.android.qml_app.jni.NativeCalls;
|
||||
|
||||
public class RetroShareQmlActivity extends QtActivity
|
||||
{
|
||||
|
||||
static final int PICK_PHOTO = 1;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
@ -84,4 +92,88 @@ public class RetroShareQmlActivity extends QtActivity
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
private Uri capturedImageURI;
|
||||
|
||||
public void openImagePicker()
|
||||
{
|
||||
Log.i("RetroShareQmlActivity", "openImagePicker()");
|
||||
|
||||
Intent pickIntent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
|
||||
pickIntent.setType("image/*");
|
||||
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(MediaStore.Images.Media.TITLE, "Retroshare Avatar");
|
||||
capturedImageURI = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
|
||||
Intent takePicture = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
|
||||
takePicture.putExtra(MediaStore.EXTRA_OUTPUT, capturedImageURI);
|
||||
|
||||
Intent chooserIntent = Intent.createChooser(pickIntent, "Select Image");
|
||||
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Intent[] {takePicture});
|
||||
|
||||
startActivityForResult( chooserIntent, PICK_PHOTO);
|
||||
};
|
||||
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data)
|
||||
{
|
||||
Log.i("RetroShareQmlActivity", "onActivityResult()" + String.valueOf(requestCode));
|
||||
|
||||
if (resultCode == RESULT_OK)
|
||||
{
|
||||
if (requestCode == PICK_PHOTO)
|
||||
{
|
||||
final boolean isCamera;
|
||||
|
||||
if (data == null)
|
||||
{
|
||||
isCamera = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
final String action = data.getAction();
|
||||
if (action == null)
|
||||
{
|
||||
isCamera = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
isCamera = action.equals(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
|
||||
}
|
||||
}
|
||||
|
||||
Uri selectedImageUri;
|
||||
if (isCamera)
|
||||
{
|
||||
selectedImageUri = capturedImageURI;
|
||||
}
|
||||
else
|
||||
{
|
||||
selectedImageUri = data == null ? null : data.getData();
|
||||
}
|
||||
|
||||
String uri = getRealPathFromURI(selectedImageUri);
|
||||
if (uri != null)
|
||||
{
|
||||
Log.i("RetroShareQmlActivity", "Image path from uri found!" + uri);
|
||||
NativeCalls.notifyIntentUri("//file"+uri); // Add the authority for get it on qml code
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String getRealPathFromURI(Uri uri) {
|
||||
String[] projection = { MediaStore.Images.Media.DATA };
|
||||
@SuppressWarnings("deprecation")
|
||||
Cursor cursor = managedQuery(uri, projection, null, null, null);
|
||||
int column_index = cursor
|
||||
.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
|
||||
cursor.moveToFirst();
|
||||
String result = cursor.getString(column_index);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
66
retroshare-qml-app/src/androidimagepicker.h
Normal file
66
retroshare-qml-app/src/androidimagepicker.h
Normal file
@ -0,0 +1,66 @@
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QDebug>
|
||||
|
||||
#include <QFile>
|
||||
#include <QUrl>
|
||||
#include <QImage>
|
||||
#include <QImageReader>
|
||||
#include <QBuffer>
|
||||
|
||||
|
||||
#ifdef __ANDROID__
|
||||
# include <QtAndroid>
|
||||
# include <QtAndroidExtras/QAndroidJniObject>
|
||||
#endif // __ANDROID__
|
||||
|
||||
struct AndroidImagePicker : QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public slots:
|
||||
|
||||
static void openPicker()
|
||||
{
|
||||
qDebug() << "Starting image picker intent";
|
||||
|
||||
#ifdef __ANDROID__
|
||||
QtAndroid::androidActivity().callMethod<void>(
|
||||
"openImagePicker",
|
||||
"()V" );
|
||||
#endif // __ANDROID__
|
||||
|
||||
}
|
||||
|
||||
// Used to convert a given image path into a png base64 string
|
||||
static QString imageToBase64 (QString const& path)
|
||||
{
|
||||
// Get local path from uri
|
||||
QUrl url (path);
|
||||
QString localPath = url.toLocalFile();
|
||||
|
||||
qDebug() << "imageToBase64() local path:" << localPath ;
|
||||
|
||||
// Read the image
|
||||
QImageReader reader;
|
||||
reader.setFileName(localPath);
|
||||
QImage image = reader.read();
|
||||
|
||||
image = image.scaled(96,96,Qt::KeepAspectRatio,Qt::SmoothTransformation);
|
||||
|
||||
// Transform image into PNG format
|
||||
QByteArray ba;
|
||||
QBuffer buffer( &ba );
|
||||
buffer.open( QIODevice::WriteOnly );
|
||||
image.save( &buffer, "png" );
|
||||
|
||||
// Get Based 64 image string
|
||||
QString encoded = QString(ba.toBase64());
|
||||
|
||||
qDebug() << "imageToBase64() encoded" ;
|
||||
|
||||
return encoded;
|
||||
|
||||
}
|
||||
};
|
60
retroshare-qml-app/src/components/CustomFileChooser.qml
Normal file
60
retroshare-qml-app/src/components/CustomFileChooser.qml
Normal file
@ -0,0 +1,60 @@
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Dialogs 1.2
|
||||
|
||||
import "../URI.js" as UriJs
|
||||
|
||||
Item
|
||||
{
|
||||
id: compRoot
|
||||
|
||||
property var resultFile
|
||||
|
||||
FileDialog
|
||||
{
|
||||
id: fileDialog
|
||||
title: "Please choose a file"
|
||||
folder: shortcuts.pictures
|
||||
nameFilters: [ "Image files (*.png *.jpg)"]
|
||||
visible: false
|
||||
selectMultiple: false
|
||||
onAccepted: {
|
||||
console.log("You chose: " + fileDialog.fileUrl)
|
||||
resultFile = fileDialog.fileUrl
|
||||
}
|
||||
onRejected: {
|
||||
console.log("Canceled")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function open()
|
||||
{
|
||||
if (Qt.platform.os === "android")
|
||||
{
|
||||
console.log("ImagePicker Android platform detected")
|
||||
mainWindow.addUriHandler("file", androidResult)
|
||||
androidImagePicker.openPicker()
|
||||
}
|
||||
else
|
||||
{
|
||||
fileDialog.visible = true
|
||||
}
|
||||
}
|
||||
|
||||
function androidResult (uri)
|
||||
{
|
||||
console.log("QML Android image uri found" , uri)
|
||||
resultFile = normalizeUriToFilePath (uri)
|
||||
mainWindow.delUriHandler("media", androidResult)
|
||||
}
|
||||
|
||||
function normalizeUriToFilePath (uriStr)
|
||||
{
|
||||
var uri = new UriJs.URI(uriStr)
|
||||
var hPath = uri.path()
|
||||
return "file:///"+hPath
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -38,9 +38,9 @@
|
||||
|
||||
#include "libresapilocalclient.h"
|
||||
#include "rsqmlappengine.h"
|
||||
#include "androidimagepicker.h"
|
||||
#include "platforminteracions.h"
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
||||
@ -52,6 +52,7 @@ int main(int argc, char *argv[])
|
||||
"org.retroshare.qml_components.LibresapiLocalClient", 1, 0,
|
||||
"LibresapiLocalClient");
|
||||
|
||||
|
||||
QString sockPath = QDir::homePath() + "/.retroshare";
|
||||
sockPath.append("/libresapi.sock");
|
||||
|
||||
@ -61,6 +62,14 @@ int main(int argc, char *argv[])
|
||||
RsQmlAppEngine engine(true);
|
||||
QQmlContext& rootContext = *engine.rootContext();
|
||||
|
||||
qmlRegisterType<AndroidImagePicker>(
|
||||
"org.retroshare.qml_components.AndroidImagePicker", 1, 0,
|
||||
"AndroidImagePicker");
|
||||
|
||||
AndroidImagePicker androidImagePicker;
|
||||
engine.rootContext()->setContextProperty("androidImagePicker",
|
||||
&androidImagePicker);
|
||||
|
||||
QStringList mainArgs = app.arguments();
|
||||
|
||||
#ifdef Q_OS_ANDROID
|
||||
|
@ -364,7 +364,7 @@ ApplicationWindow
|
||||
|
||||
function handleIntentUri(uriStr)
|
||||
{
|
||||
console.log("handleIntentUri(uriStr)")
|
||||
console.log("handleIntentUri(uriStr)", uriStr)
|
||||
|
||||
if(!Array.isArray(uriStr.match(/:\/\/[a-zA-Z.-]*\//g)))
|
||||
{
|
||||
@ -382,7 +382,10 @@ ApplicationWindow
|
||||
|
||||
var uri = new UriJs.URI(uriStr)
|
||||
var hPath = uri.path() // no nesting ATM segmentCoded()
|
||||
console.log(hPath)
|
||||
console.log("hPath", hPath)
|
||||
|
||||
var authority = uri.authority()
|
||||
console.log("authority", authority)
|
||||
|
||||
if(typeof uriHandlersRegister[hPath] == "function")
|
||||
{
|
||||
@ -390,6 +393,13 @@ ApplicationWindow
|
||||
hPath, uriHandlersRegister[hPath])
|
||||
uriHandlersRegister[hPath](uriStr)
|
||||
}
|
||||
|
||||
else if (typeof uriHandlersRegister[authority] == "function" )
|
||||
{
|
||||
console.log("handleIntentUri(uriStr)", "found handler for path",
|
||||
authority, uriHandlersRegister[authority])
|
||||
uriHandlersRegister[authority](uriStr)
|
||||
}
|
||||
}
|
||||
|
||||
function certificateLinkHandler(uriStr)
|
||||
|
@ -53,5 +53,6 @@
|
||||
<file>components/emoji/emoji.js</file>
|
||||
<file>icons/network-connect.svg</file>
|
||||
<file>icons/network-disconnect.svg</file>
|
||||
<file>components/CustomFileChooser.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
@ -6,6 +6,7 @@ CONFIG += c++11
|
||||
|
||||
HEADERS += libresapilocalclient.h \
|
||||
rsqmlappengine.h \
|
||||
androidimagepicker.h \
|
||||
platforminteracions.h
|
||||
SOURCES += main-app.cpp \
|
||||
libresapilocalclient.cpp \
|
||||
|
Loading…
Reference in New Issue
Block a user