Merge lp:~renatofilho/address-book-app/fix-1511478 into lp:address-book-app

Proposed by Renato Araujo Oliveira Filho
Status: Superseded
Proposed branch: lp:~renatofilho/address-book-app/fix-1511478
Merge into: lp:address-book-app
Diff against target: 363 lines (+102/-50)
9 files modified
src/imports/Ubuntu/AddressBook/ContactEditor/AvatarImport.qml (+1/-4)
src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailAvatarEditor.qml (+26/-5)
src/imports/Ubuntu/Contacts/contacts.cpp (+10/-21)
src/imports/Ubuntu/Contacts/contacts.h (+2/-1)
src/imports/Ubuntu/Contacts/imagescalethread.cpp (+25/-11)
src/imports/Ubuntu/Contacts/imagescalethread.h (+7/-5)
tests/autopilot/address_book_app/__init__.py (+2/-1)
tests/autopilot/address_book_app/pages/__init__.py (+1/-2)
tests/autopilot/address_book_app/pages/_ab_contact_editor_page.py (+28/-0)
To merge this branch: bzr merge lp:~renatofilho/address-book-app/fix-1511478
Reviewer Review Type Date Requested Status
Ubuntu Phablet Team Pending
Review via email: mp+276166@code.launchpad.net

This proposal has been superseded by a proposal from 2015-10-29.

To post a comment you must log in.
495. By Renato Araujo Oliveira Filho

Trunk merged.

496. By Renato Araujo Oliveira Filho

Trunk merged.

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/imports/Ubuntu/AddressBook/ContactEditor/AvatarImport.qml'
--- src/imports/Ubuntu/AddressBook/ContactEditor/AvatarImport.qml 2015-10-26 13:18:11 +0000
+++ src/imports/Ubuntu/AddressBook/ContactEditor/AvatarImport.qml 2015-10-29 18:12:58 +0000
@@ -59,7 +59,6 @@
59 id: peerPicker59 id: peerPicker
6060
61 anchors.fill: parent61 anchors.fill: parent
62 visible: dialogue.done
63 contentType: ContentType.Pictures62 contentType: ContentType.Pictures
64 handler: ContentHandler.Source63 handler: ContentHandler.Source
6564
@@ -77,13 +76,11 @@
77 Connections {76 Connections {
78 id: signalConnections77 id: signalConnections
7978
80 target: dialogue.activeTransfer
81 onStateChanged: {79 onStateChanged: {
82 var done = ((dialogue.activeTransfer.state === ContentTransfer.Charged) ||80 var done = ((dialogue.activeTransfer.state === ContentTransfer.Charged) ||
83 (dialogue.activeTransfer.state === ContentTransfer.Aborted))81 (dialogue.activeTransfer.state === ContentTransfer.Aborted))
8482
85 if (dialogue.activeTransfer.state === ContentTransfer.Charged) {83 if (dialogue.activeTransfer.state === ContentTransfer.Charged) {
86 dialogue.hide()
87 if (dialogue.activeTransfer.items.length > 0) {84 if (dialogue.activeTransfer.items.length > 0) {
88 root.avatarReceived(dialogue.activeTransfer.items[0].url)85 root.avatarReceived(dialogue.activeTransfer.items[0].url)
89 }86 }
@@ -108,7 +105,7 @@
108 repeat: true105 repeat: true
109 running: false106 running: false
110 onTriggered: {107 onTriggered: {
111 if(Qt.application.active) {108 if(Qt.application.state === Qt.ApplicationActive) {
112 PopupUtils.close(root.importDialog)109 PopupUtils.close(root.importDialog)
113 }110 }
114 }111 }
115112
=== modified file 'src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailAvatarEditor.qml'
--- src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailAvatarEditor.qml 2015-10-26 13:18:11 +0000
+++ src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailAvatarEditor.qml 2015-10-29 18:12:58 +0000
@@ -27,6 +27,8 @@
2727
28 readonly property alias busy: activityIndicator.running28 readonly property alias busy: activityIndicator.running
29 readonly property string defaultAvatar: "image://theme/add"29 readonly property string defaultAvatar: "image://theme/add"
30 property string temporaryAvatar: ""
31 property string temporaryAvatarId: ""
3032
31 function isEmpty() {33 function isEmpty() {
32 return false;34 return false;
@@ -86,8 +88,8 @@
86 width: units.gu(3)88 width: units.gu(3)
87 visible: source == defaultAvatar89 visible: source == defaultAvatar
88 sourceSize {90 sourceSize {
89 width: units.gu(3)91 width: avatarImage.visible ? units.gu(3) : avatar.width
90 height: units.gu(3)92 height: avatarImage.visible ? units.gu(3) : avatar.height
91 }93 }
9294
93 // When updating the avatar using the content picker the temporary file returned95 // When updating the avatar using the content picker the temporary file returned
@@ -101,7 +103,7 @@
101 id: activityIndicator103 id: activityIndicator
102104
103 anchors.centerIn: avatar105 anchors.centerIn: avatar
104 running: (avatarImport.importDialog != null)106 running: (avatarImport.importDialog != null) || (root.temporaryAvatarId != "")
105 visible: running107 visible: running
106 }108 }
107109
@@ -109,12 +111,25 @@
109 id: avatarImport111 id: avatarImport
110112
111 onAvatarReceived: {113 onAvatarReceived: {
114 Contacts.removeFile(root.temporaryAvatar)
115
112 // remove the previous image, this is nessary to make sure that the new image116 // remove the previous image, this is nessary to make sure that the new image
113 // get updated otherwise if the new image has the same name the image will not117 // get updated otherwise if the new image has the same name the image will not
114 // be updated118 // be updated
115 avatarImage.source = ""119 avatarImage.source = ""
116 // Update with the new value120 // copy and resize image
117 avatarImage.source = Contacts.copyImage(root.contact, avatarUrl);121 root.temporaryAvatarId = Contacts.copyImage(avatarUrl, null);
122 }
123 }
124
125 Connections {
126 target: Contacts
127 onImageCopyDone: {
128 if (root.temporaryAvatarId === id) {
129 root.temporaryAvatar = fileName
130 avatarImage.source = fileName
131 root.temporaryAvatarId = ""
132 }
118 }133 }
119 }134 }
120135
@@ -126,6 +141,12 @@
126 avatarImport.requestNewAvatar()141 avatarImport.requestNewAvatar()
127 }142 }
128 }143 }
144
145 Component.onDestruction: {
146 console.debug("Delete temporary avatar image:" + root.temporaryAvatar)
147 Contacts.removeFile("file:///" + root.temporaryAvatar)
148 root.temporaryAvatar = ""
149 }
129}150}
130151
131152
132153
=== modified file 'src/imports/Ubuntu/Contacts/contacts.cpp'
--- src/imports/Ubuntu/Contacts/contacts.cpp 2015-10-14 22:53:35 +0000
+++ src/imports/Ubuntu/Contacts/contacts.cpp 2015-10-29 18:12:58 +0000
@@ -23,6 +23,7 @@
23#include <QtCore/QDir>23#include <QtCore/QDir>
24#include <QtCore/QUrl>24#include <QtCore/QUrl>
25#include <QtCore/QLockFile>25#include <QtCore/QLockFile>
26#include <QtCore/QThreadPool>
2627
27#include "config.h"28#include "config.h"
2829
@@ -77,27 +78,11 @@
77 return out;78 return out;
78}79}
7980
80QUrl UbuntuContacts::copyImage(QObject *contact, const QUrl &imageUrl)81QString UbuntuContacts::copyImage(const QUrl &imageUrl)
81{82{
82 // keep track of threads to avoid memory leeak83 ImageScaleThread *imgThread = new ImageScaleThread(imageUrl, this);
83 ImageScaleThread *imgThread;84 QThreadPool::globalInstance()->start(imgThread);
84 QVariant oldThread = contact->property("IMAGE_SCALE_THREAD");85 return imgThread->id();
85 if (!oldThread.isNull()) {
86 imgThread = oldThread.value<ImageScaleThread *>();
87 imgThread->updateImageUrl(imageUrl);
88 } else {
89 imgThread = new ImageScaleThread(imageUrl, contact);
90 contact->setProperty("IMAGE_SCALE_THREAD", QVariant::fromValue<ImageScaleThread*>(imgThread));
91 }
92
93 imgThread->start();
94
95 // FIXME: implement this as async function
96 while(imgThread->isRunning()) {
97 QCoreApplication::processEvents(QEventLoop::AllEvents, 3000);
98 }
99
100 return imgThread->outputFile();
101}86}
10287
103bool UbuntuContacts::containsLetters(const QString &value)88bool UbuntuContacts::containsLetters(const QString &value)
@@ -112,7 +97,11 @@
11297
113bool UbuntuContacts::removeFile(const QUrl &file)98bool UbuntuContacts::removeFile(const QUrl &file)
114{99{
115 return QFile::remove(file.toLocalFile());100 QString localFile = file.toLocalFile();
101 if (!localFile.isEmpty() && QFile::exists(localFile)) {
102 return QFile::remove(localFile);
103 }
104 return false;
116}105}
117106
118bool UbuntuContacts::updateIsRunning() const107bool UbuntuContacts::updateIsRunning() const
119108
=== modified file 'src/imports/Ubuntu/Contacts/contacts.h'
--- src/imports/Ubuntu/Contacts/contacts.h 2015-10-13 12:50:14 +0000
+++ src/imports/Ubuntu/Contacts/contacts.h 2015-10-29 18:12:58 +0000
@@ -36,12 +36,13 @@
3636
37 Q_INVOKABLE QString contactInitialsFromString(const QString &value);37 Q_INVOKABLE QString contactInitialsFromString(const QString &value);
38 Q_INVOKABLE QString normalized(const QString &value);38 Q_INVOKABLE QString normalized(const QString &value);
39 Q_INVOKABLE QUrl copyImage(QObject *contact, const QUrl &imageUrl);39 Q_INVOKABLE QString copyImage(const QUrl &imageUrl);
40 Q_INVOKABLE bool containsLetters(const QString &value);40 Q_INVOKABLE bool containsLetters(const QString &value);
41 Q_INVOKABLE bool removeFile(const QUrl &file);41 Q_INVOKABLE bool removeFile(const QUrl &file);
42 Q_INVOKABLE bool updateIsRunning() const;42 Q_INVOKABLE bool updateIsRunning() const;
4343
44Q_SIGNALS:44Q_SIGNALS:
45 void imageCopyDone(const QString &id, const QString &fileName);
45 void updateIsRunningChanged();46 void updateIsRunningChanged();
4647
47private:48private:
4849
=== modified file 'src/imports/Ubuntu/Contacts/imagescalethread.cpp'
--- src/imports/Ubuntu/Contacts/imagescalethread.cpp 2015-05-07 17:27:16 +0000
+++ src/imports/Ubuntu/Contacts/imagescalethread.cpp 2015-10-29 18:12:58 +0000
@@ -20,39 +20,46 @@
20#include <QImageReader>20#include <QImageReader>
21#include <QFile>21#include <QFile>
22#include <QDir>22#include <QDir>
23#include <QUuid>
23#include <QDebug>24#include <QDebug>
2425
25ImageScaleThread::ImageScaleThread(const QUrl &imageUrl, QObject *parent)26ImageScaleThread::ImageScaleThread(const QUrl &imageUrl, QObject *listener)
26 : QThread(parent),27 : m_imageUrl(imageUrl),
27 m_imageUrl(imageUrl),28 m_id(QUuid::createUuid().toString()),
28 m_tmpFile(0)29 m_listener(listener),
30 m_tmpFile(0)
29{31{
30}32}
3133
32ImageScaleThread::~ImageScaleThread()34ImageScaleThread::~ImageScaleThread()
33{35{
34 if (m_tmpFile) {36 if (m_tmpFile) {
35 delete m_tmpFile;37 m_tmpFile->setAutoRemove(false);
38 m_tmpFile->deleteLater();
39 m_tmpFile = 0;
36 }40 }
37}41}
3842
39void ImageScaleThread::updateImageUrl(const QUrl &imageUrl)43QString ImageScaleThread::id()
40{44{
41 if (isRunning()) {45 return m_id;
42 wait();
43 }
44 m_imageUrl = imageUrl;
45}46}
4647
47QString ImageScaleThread::outputFile() const48QString ImageScaleThread::outputFile() const
48{49{
49 return m_tmpFile->fileName();50 if (m_tmpFile) {
51 return m_tmpFile->fileName();
52 } else {
53 return QString();
54 }
50}55}
5156
52void ImageScaleThread::run()57void ImageScaleThread::run()
53{58{
54 // make sure that the old image get deleted59 // make sure that the old image get deleted
55 if (m_tmpFile) {60 if (m_tmpFile) {
61 qDebug() << "Delete previous avatar" << m_tmpFile->fileName();
62 m_tmpFile->setAutoRemove(true);
56 m_tmpFile->close();63 m_tmpFile->close();
57 delete m_tmpFile;64 delete m_tmpFile;
58 }65 }
@@ -60,6 +67,7 @@
60 // Create the temporary file67 // Create the temporary file
61 m_tmpFile = new QTemporaryFile(QString("%1/avatar_XXXXXX.png").arg(QDir::tempPath()));68 m_tmpFile = new QTemporaryFile(QString("%1/avatar_XXXXXX.png").arg(QDir::tempPath()));
62 if (!m_tmpFile->open()) {69 if (!m_tmpFile->open()) {
70 qWarning() << "Fail to create avatar temporary file";
63 return;71 return;
64 }72 }
6573
@@ -91,5 +99,11 @@
91 if (!scaledAvatar.isNull()) {99 if (!scaledAvatar.isNull()) {
92 scaledAvatar.save(m_tmpFile, "png");100 scaledAvatar.save(m_tmpFile, "png");
93 }101 }
102
94 m_tmpFile->close();103 m_tmpFile->close();
104
105 if (m_listener) {
106 QMetaObject::invokeMethod(m_listener, "imageCopyDone",
107 Q_ARG(QString, m_id), Q_ARG(QString, m_tmpFile->fileName()));
108 }
95}109}
96110
=== modified file 'src/imports/Ubuntu/Contacts/imagescalethread.h'
--- src/imports/Ubuntu/Contacts/imagescalethread.h 2015-05-07 17:27:16 +0000
+++ src/imports/Ubuntu/Contacts/imagescalethread.h 2015-10-29 18:12:58 +0000
@@ -18,18 +18,18 @@
18#define IMAGESCALETHREAD_H18#define IMAGESCALETHREAD_H
1919
20#include <QObject>20#include <QObject>
21#include <QThread>21#include <QRunnable>
22#include <QUrl>22#include <QUrl>
23#include <QPointer>
23#include <QTemporaryFile>24#include <QTemporaryFile>
2425
25class ImageScaleThread : public QThread26class ImageScaleThread : public QRunnable
26{27{
27 Q_OBJECT
28public:28public:
29 ImageScaleThread(const QUrl &imageUrl, QObject *parent=0);29 ImageScaleThread(const QUrl &imageUrl, QObject *listener);
30 ~ImageScaleThread();30 ~ImageScaleThread();
3131
32 void updateImageUrl(const QUrl &imageUrl);32 QString id();
33 QString outputFile() const;33 QString outputFile() const;
3434
35protected:35protected:
@@ -37,6 +37,8 @@
3737
38private:38private:
39 QUrl m_imageUrl;39 QUrl m_imageUrl;
40 QString m_id;
41 QPointer<QObject> m_listener;
40 QTemporaryFile *m_tmpFile;42 QTemporaryFile *m_tmpFile;
41};43};
4244
4345
=== modified file 'tests/autopilot/address_book_app/__init__.py'
--- tests/autopilot/address_book_app/__init__.py 2015-10-20 03:38:07 +0000
+++ tests/autopilot/address_book_app/__init__.py 2015-10-29 18:12:58 +0000
@@ -70,7 +70,8 @@
70 def get_contact_edit_page(self):70 def get_contact_edit_page(self):
71 # We can have two contact editor page because of bottom edge page71 # We can have two contact editor page because of bottom edge page
72 # but we will return only the active one72 # but we will return only the active one
73 return self.wait_select_single(objectName="contactEditorPage", active=True)73 return self.wait_select_single(pages.ABContactEditorPage,
74 objectName="contactEditorPage", active=True)
7475
75 def get_contact_view_page(self):76 def get_contact_view_page(self):
76 return self.wait_select_single(pages.ABContactViewPage,77 return self.wait_select_single(pages.ABContactViewPage,
7778
=== modified file 'tests/autopilot/address_book_app/pages/__init__.py'
--- tests/autopilot/address_book_app/pages/__init__.py 2015-05-11 14:21:03 +0000
+++ tests/autopilot/address_book_app/pages/__init__.py 2015-10-29 18:12:58 +0000
@@ -20,7 +20,6 @@
20 'ABContactViewPage'20 'ABContactViewPage'
21]21]
2222
23from address_book_app.address_book \23from address_book_app.pages._ab_contact_editor_page import ABContactEditorPage
24 import ContactEditorPage as ABContactEditorPage
25from address_book_app.pages._ab_contact_view_page import ABContactViewPage24from address_book_app.pages._ab_contact_view_page import ABContactViewPage
26from address_book_app.pages._ab_contact_list_page import ABContactListPage25from address_book_app.pages._ab_contact_list_page import ABContactListPage
2726
=== added file 'tests/autopilot/address_book_app/pages/_ab_contact_editor_page.py'
--- tests/autopilot/address_book_app/pages/_ab_contact_editor_page.py 1970-01-01 00:00:00 +0000
+++ tests/autopilot/address_book_app/pages/_ab_contact_editor_page.py 2015-10-29 18:12:58 +0000
@@ -0,0 +1,28 @@
1# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
2#
3# Copyright (C) 2014 Canonical Ltd.
4#
5# This program is free software; you can redistribute it and/or modify
6# it under the terms of the GNU General Public License version 3, as published
7# by the Free Software Foundation.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU General Public License for more details.
13#
14# You should have received a copy of the GNU General Public License
15# along with this program. If not, see <http://www.gnu.org/licenses/>.
16
17""" ContactEditorPage emulator for Addressbook App tests """
18
19import logging
20import time
21
22import autopilot.logging
23import ubuntuuitoolkit
24
25from address_book_app import address_book
26
27class ABContactEditorPage(address_book.ContactEditorPage):
28 """Autopilot helper for the Contact Editor page."""

Subscribers

People subscribed via source and target branches