Merge pull request #1058 from G10h4ck/qml_app_development

Qml app improvements
This commit is contained in:
Gioacchino 2017-10-10 12:53:20 +02:00 committed by GitHub
commit 3b781f04dd
7 changed files with 202 additions and 167 deletions

View File

@ -28,7 +28,7 @@ Item
{
id: chatView
property string chatId
property var gxsInfo: ""
property var gxsInfo: ({})
property int token: 0
property string objectName:"chatView"
@ -64,7 +64,7 @@ Item
function changeState ()
{
toolBar.state = "CHATVIEW"
gxsInfo= ChatCache.lastMessageCache.getGxsFromChatId(chatView.chatId)
gxsInfo = ChatCache.lastMessageCache.getGxsFromChatId(chatView.chatId)
toolBar.gxsSource = gxsInfo.gxs
toolBar.titleText = gxsInfo.name
}
@ -100,7 +100,7 @@ Item
anchors.fill: parent
anchors.topMargin: parent.height / 2
anchors.bottomMargin: categorySelectorHeight
anchors.bottomMargin: if(!androidMode) categorySelectorHeight
property int categorySelectorHeight: 50
@ -114,6 +114,7 @@ Item
name: "EMOJI_HIDDEN"
PropertyChanges { target: emojiPicker; anchors.topMargin: parent.height }
PropertyChanges { target: emojiPicker; anchors.bottomMargin: -1 }
PropertyChanges { target: emojiPicker; height: 0 }
},
State {
name: "EMOJI_SHOWN"
@ -132,7 +133,7 @@ Item
id: inferiorPanel
height: ( msgComposer.height > styles.height)? msgComposer.height: styles.height
width: parent.width
anchors.bottom: parent.bottom
anchors.bottom: emojiPicker.androidMode ? emojiPicker.top : parent.bottom
Rectangle
{

View File

@ -50,7 +50,14 @@ Item
console.log("GxsIntentityDelegate onclicked:", model.name,
model.gxs_id)
contactsView.searching = false
if(model.own) contactsView.own_gxs_id = model.gxs_id
if(model.own)
{
contactsView.own_gxs_id = model.gxs_id
stackView.push(
"qrc:/ContactDetails.qml",
{md: ChatCache.contactsCache.getContactFromGxsId(model.gxs_id)})
}
else
{
startDistantChat()

View File

@ -9,6 +9,8 @@
#include <QImageReader>
#include <QBuffer>
#include "qpainter.h"
#ifdef __ANDROID__
# include <QtAndroid>
@ -41,14 +43,44 @@ public slots:
QString localPath = url.toLocalFile();
qDebug() << "imageToBase64() local path:" << localPath ;
// Read the image
QImageReader reader;
reader.setFileName(localPath);
QImage image = reader.read();
QImage image= getImage (localPath);
image = image.scaled(96,96,Qt::KeepAspectRatio,Qt::SmoothTransformation);
qDebug() << "imageToBase64() encoding" ;
return imageToB64(image);
}
static QString b64AvatarGen (QVariantList onloads, int size)
{
qDebug() << "b64AvatarGen(): Generating face Avatar from";
QImage result(size, size, QImage::Format_ARGB32_Premultiplied);
QPainter painter(&result);
int counter = 0;
for (QVariantList::iterator j = onloads.begin(); j != onloads.end(); j++)
{
QImage image = getImage (":/"+(*j).toString());
painter.drawImage(0, 0, image); // xi, yi is the position for imagei
counter++;
}
painter.end();
return imageToB64(result);
}
static QImage getImage (QString const& path)
{
QImageReader reader;
reader.setFileName(path);
return reader.read();
}
static QString imageToB64 (QImage image)
{
// Transform image into PNG format
QByteArray ba;
QBuffer buffer( &ba );
@ -56,11 +88,8 @@ public slots:
image.save( &buffer, "png" );
// Get Based 64 image string
QString encoded = QString(ba.toBase64());
qDebug() << "imageToBase64() encoded" ;
return encoded;
return QString(ba.toBase64());
}
};

View File

@ -4,64 +4,22 @@ import "../" // Needed by ChatCache (where stores generated faces)
Item
{
id: faces
property string hash
property var facesCache: ChatCache.facesCache
Image
{
id: imageAvatar
width: height
height: iconSize
visible: true
}
Canvas
{
id: canvasAvatar
width: height
height: canvasSizes
visible: false
renderStrategy: Canvas.Threaded;
renderTarget: Canvas.Image;
property var images
property var callback
onPaint:
{
var ctx = getContext("2d");
if (images)
{
for (y = 0 ; y< nPieces ; y++)
{
ctx.drawImage(images[y], 0, 0, iconSize, iconSize )
}
}
}
onPainted:
{
if (callback)
{
var data = toDataURL('image/png')
callback(data)
}
}
}
Component.onCompleted:
{
createFromHex(hash)
}
Component.onCompleted: createFromHex(hash)
/* TODO: Is there a reason why we are using var and not proper type for the
* following properties? */
property var facesPath: "/icons/faces/"
@ -134,11 +92,9 @@ Item
{
var url = src(gender, i, data[i+1])
onloads.push(url)
canvasAvatar.loadImage(url)
}
canvasAvatar.images = onloads
canvasAvatar.callback = callback
canvasAvatar.requestPaint()
var base64Image = androidImagePicker.b64AvatarGen(onloads, canvasSizes)
callback("data:image/png;base64,"+base64Image)
}
// Create the identicon
@ -146,32 +102,11 @@ Item
{
var iconId = [dataHex, iconSize];
var update = function(data)
{
// This conditions are for solve a bug on an Lg S3.
// On this device the toDataURL() is incompleted.
// So for see the complete avatar at least at first execution we'll show the canvas,
// instead of the image component.
// See issue: https://gitlab.com/angesoc/RetroShare/issues/37
if (facesCache.iconCache[iconId])
{
imageAvatar.source = data
imageAvatar.visible = true
canvasAvatar.visible = false
canvasAvatar.height = 0
imageAvatar.height = iconSize
}
else
{
canvasAvatar.visible = true
imageAvatar.visible = false
canvasAvatar.height = iconSize
imageAvatar.height = 0
}
facesCache.iconCache[iconId] = data;
}
{
imageAvatar.source = data
imageAvatar.height = iconSize
facesCache.iconCache[iconId] = data;
}
if (facesCache.iconCache.hasOwnProperty(iconId))
{
@ -184,13 +119,13 @@ Item
else
{
var onImageGenerated = function(data)
{
{
facesCache.callbackCache[iconId].forEach(function(callback)
{
callback(data);
})
}
facesCache.callbackCache[iconId].forEach(function(callback)
{
callback(data);
})
}
facesCache.callbackCache[iconId] = [update];
if (dataHex)

View File

@ -1,12 +1,14 @@
import QtQuick 2.7
import QtQuick.Controls.Styles 1.2
Rectangle {
Rectangle
{
id: emojiButton
property var fontName
Text {
Text
{
id: emojiText
color: "gray"
text: qsTr(eCatText)
@ -17,17 +19,22 @@ Rectangle {
state: "RELEASED"
states: [
State {
states:
[
State
{
name: "PRESSED"
PropertyChanges {
PropertyChanges
{
target: emojiText
font.pixelSize: emojiButton.width - 10
}
},
State {
State
{
name: "RELEASED"
PropertyChanges {
PropertyChanges
{
target: emojiText
font.pixelSize: emojiButton.width - 8
}
@ -35,20 +42,25 @@ Rectangle {
]
MouseArea {
MouseArea
{
anchors.fill: parent
hoverEnabled: true
onEntered: {
onEntered:
{
emojiText.color = "black"
}
onExited: {
onExited:
{
emojiText.color = "gray"
}
onPressedChanged: {
onPressedChanged:
{
emojiButton.state = emojiButton.state == "PRESSED" ? "RELEASED" : "PRESSED"
}
onClicked: {
onClicked:
{
Qt.emojiClickedHandler(emojiText.text)
}
}

View File

@ -1,30 +1,37 @@
import QtQuick 2.7
import QtQuick.Controls.Styles 1.2
Rectangle {
Rectangle
{
id: emojiCategoryButton
property string categoryName
property var fontName
function completedHandler() {
function completedHandler()
{
categoryName = eCatName
//initialize
if (parent.currSelEmojiButton === undefined) {
if (parent.currSelEmojiButton === undefined)
{
clickedHandler()
}
}
function pressedHandler() {
if (state != "SELECTED") {
function pressedHandler()
{
if (state != "SELECTED")
{
state = state == "PRESSED" ? "RELEASED" : "PRESSED"
}
}
function clickedHandler() {
if (parent.currSelEmojiButton !== undefined) {
function clickedHandler()
{
if (parent.currSelEmojiButton !== undefined)
{
parent.currSelEmojiButton.state = "RELEASED"
}
@ -34,7 +41,8 @@ Rectangle {
}
Text {
Text
{
id: emojiText
color: "gray"
text: qsTr(eCatText)
@ -45,31 +53,39 @@ Rectangle {
state: "RELEASED"
states: [
State {
states:
[
State
{
name: "PRESSED"
PropertyChanges {
PropertyChanges
{
target: emojiText
font.pixelSize: emojiCategoryButton.width - 10
}
},
State {
State
{
name: "RELEASED"
PropertyChanges {
PropertyChanges
{
target: emojiText
font.pixelSize: emojiCategoryButton.width - 8
}
},
State {
State
{
name: "SELECTED"
PropertyChanges {
PropertyChanges
{
target: emojiCategoryButton
color: "#ADD6FF"
}
}
]
MouseArea {
MouseArea
{
anchors.fill: parent
hoverEnabled: true
onEntered: emojiText.color = "black"

View File

@ -2,33 +2,41 @@ import QtQuick 2.7
import QtQuick.Controls 2.0
import "emoji.js" as EmojiJSON
Rectangle {
Rectangle
{
id: emojiPicker
property EmojiCategoryButton currSelEmojiButton
property variant emojiParsedJson
property int buttonWidth: 40
property TextArea textArea
property bool androidMode: Qt.platform.os === "android" // On Desktop appears on top of text field, instead appears in place of virtual keyboard (under text field)
property var rootFontName: theme.emojiFontName
//displays all Emoji of one categroy by modifying the ListModel of emojiGrid
function categoryChangedHandler (newCategoryName){
function categoryChangedHandler (newCategoryName)
{
emojiByCategory.clear()
for (var i = 0; i < emojiParsedJson.emoji_by_category[newCategoryName].length; i++) {
for (var i = 0; i < emojiParsedJson.emoji_by_category[newCategoryName].length; i++)
{
var elem = emojiParsedJson.emoji_by_category[newCategoryName][i]
emojiByCategory.append({eCatName: newCategoryName, eCatText: elem})
}
}
//adds the clicked Emoji (and one ' ' if the previous character isn't an Emoji) to textArea
function emojiClickedHandler(selectedEmoji) {
function emojiClickedHandler(selectedEmoji)
{
var strAppnd = ""
var plainText = textArea.getText(0, textArea.length)
if (plainText.length > 0) {
var lastChar = plainText[plainText.length-1]
if ((lastChar !== ' ') && (lastChar.charCodeAt(0) < 255)) {
if ((lastChar !== ' ') && (lastChar.charCodeAt(0) < 255))
{
strAppnd = " "
}
}
@ -38,10 +46,12 @@ Rectangle {
}
//parses JSON, publishes button handlers and inits textArea
function completedHandler() {
function completedHandler()
{
// emojiParsedJson = JSON.parse(EmojiJSON.emoji_json)
emojiParsedJson = EmojiJSON.emoji_json
for (var i = 0; i < emojiParsedJson.emoji_categories.length; i++) {
for (var i = 0; i < emojiParsedJson.emoji_categories.length; i++)
{
var elem = emojiParsedJson.emoji_categories[i]
emojiCategoryButtons.append({eCatName: elem.name, eCatText: elem.emoji_unified})
}
@ -56,29 +66,39 @@ Rectangle {
//checks if the previous character is an Emoji and adds a ' ' if that's the case
//this is necessary, because Emoji use a bigger font-size, and that font-size is kept using without a ' '
function keyPressedHandler(event) {
function keyPressedHandler(event)
{
var testStr = textArea.getText(textArea.length-2, textArea.length)
var ptrn = new RegExp("[\uD800-\uDBFF][\uDC00-\uDFFF]")
if ((event.key !== Qt.Key_Backspace) && (ptrn.test(testStr))) {
if ((event.key !== Qt.Key_Backspace) && (ptrn.test(testStr)))
{
textArea.text += " "
textArea.cursorPosition = textArea.length
}
}
//all emoji of one category
ListModel {
ListModel
{
id: emojiByCategory
}
GridView {
GridView
{
id: emojiGrid
width: parent.width
anchors.fill: parent
anchors.bottomMargin: buttonWidth
cellWidth: buttonWidth; cellHeight: buttonWidth
anchors.fill: parent
anchors
{
bottomMargin: if (!androidMode) buttonWidth
topMargin: if (androidMode) buttonWidth
}
cellWidth: buttonWidth; cellHeight: buttonWidth
model: emojiByCategory
delegate: EmojiButton {
delegate: EmojiButton
{
width: buttonWidth
height: buttonWidth
color: emojiPicker.color
@ -88,37 +108,52 @@ Rectangle {
//seperator
Rectangle {
color: emojiPicker.color
anchors.bottom: parent.bottom
Rectangle
{
color: "gray"
anchors
{
bottom: if (!androidMode) parent.bottom
top: if (androidMode) parent.top
bottomMargin: if (!androidMode) buttonWidth
topMargin: if (androidMode) buttonWidth
}
width: parent.width
height: 1
}
Rectangle
{
color: emojiPicker.color
width: parent.width
height: buttonWidth
}
Rectangle {
color: "black"
anchors.bottom: parent.bottom
anchors.bottomMargin: buttonWidth
width: parent.width
height: 1
anchors
{
bottom: if (!androidMode) parent.bottom
top: if (androidMode) parent.top
}
//emoji category selector
ListView
{
width: parent.width
orientation: ListView.Horizontal
anchors.fill: parent
model: emojiCategoryButtons
delegate: EmojiCategoryButton
{
width: buttonWidth
height: buttonWidth
color: emojiPicker.color
fontName: rootFontName
}
}
}
//emoji category selector
ListView {
width: parent.width
anchors.bottom: parent.bottom
anchors.bottomMargin: buttonWidth
orientation: ListView.Horizontal
model: emojiCategoryButtons
delegate: EmojiCategoryButton {
width: buttonWidth
height: buttonWidth
color: emojiPicker.color
fontName: rootFontName
}
}
ListModel {
ListModel
{
id: emojiCategoryButtons
}