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
1=== modified file 'src/imports/Ubuntu/AddressBook/ContactEditor/AvatarImport.qml'
2--- src/imports/Ubuntu/AddressBook/ContactEditor/AvatarImport.qml 2015-10-26 13:18:11 +0000
3+++ src/imports/Ubuntu/AddressBook/ContactEditor/AvatarImport.qml 2015-10-29 18:12:58 +0000
4@@ -59,7 +59,6 @@
5 id: peerPicker
6
7 anchors.fill: parent
8- visible: dialogue.done
9 contentType: ContentType.Pictures
10 handler: ContentHandler.Source
11
12@@ -77,13 +76,11 @@
13 Connections {
14 id: signalConnections
15
16- target: dialogue.activeTransfer
17 onStateChanged: {
18 var done = ((dialogue.activeTransfer.state === ContentTransfer.Charged) ||
19 (dialogue.activeTransfer.state === ContentTransfer.Aborted))
20
21 if (dialogue.activeTransfer.state === ContentTransfer.Charged) {
22- dialogue.hide()
23 if (dialogue.activeTransfer.items.length > 0) {
24 root.avatarReceived(dialogue.activeTransfer.items[0].url)
25 }
26@@ -108,7 +105,7 @@
27 repeat: true
28 running: false
29 onTriggered: {
30- if(Qt.application.active) {
31+ if(Qt.application.state === Qt.ApplicationActive) {
32 PopupUtils.close(root.importDialog)
33 }
34 }
35
36=== modified file 'src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailAvatarEditor.qml'
37--- src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailAvatarEditor.qml 2015-10-26 13:18:11 +0000
38+++ src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailAvatarEditor.qml 2015-10-29 18:12:58 +0000
39@@ -27,6 +27,8 @@
40
41 readonly property alias busy: activityIndicator.running
42 readonly property string defaultAvatar: "image://theme/add"
43+ property string temporaryAvatar: ""
44+ property string temporaryAvatarId: ""
45
46 function isEmpty() {
47 return false;
48@@ -86,8 +88,8 @@
49 width: units.gu(3)
50 visible: source == defaultAvatar
51 sourceSize {
52- width: units.gu(3)
53- height: units.gu(3)
54+ width: avatarImage.visible ? units.gu(3) : avatar.width
55+ height: avatarImage.visible ? units.gu(3) : avatar.height
56 }
57
58 // When updating the avatar using the content picker the temporary file returned
59@@ -101,7 +103,7 @@
60 id: activityIndicator
61
62 anchors.centerIn: avatar
63- running: (avatarImport.importDialog != null)
64+ running: (avatarImport.importDialog != null) || (root.temporaryAvatarId != "")
65 visible: running
66 }
67
68@@ -109,12 +111,25 @@
69 id: avatarImport
70
71 onAvatarReceived: {
72+ Contacts.removeFile(root.temporaryAvatar)
73+
74 // remove the previous image, this is nessary to make sure that the new image
75 // get updated otherwise if the new image has the same name the image will not
76 // be updated
77 avatarImage.source = ""
78- // Update with the new value
79- avatarImage.source = Contacts.copyImage(root.contact, avatarUrl);
80+ // copy and resize image
81+ root.temporaryAvatarId = Contacts.copyImage(avatarUrl, null);
82+ }
83+ }
84+
85+ Connections {
86+ target: Contacts
87+ onImageCopyDone: {
88+ if (root.temporaryAvatarId === id) {
89+ root.temporaryAvatar = fileName
90+ avatarImage.source = fileName
91+ root.temporaryAvatarId = ""
92+ }
93 }
94 }
95
96@@ -126,6 +141,12 @@
97 avatarImport.requestNewAvatar()
98 }
99 }
100+
101+ Component.onDestruction: {
102+ console.debug("Delete temporary avatar image:" + root.temporaryAvatar)
103+ Contacts.removeFile("file:///" + root.temporaryAvatar)
104+ root.temporaryAvatar = ""
105+ }
106 }
107
108
109
110=== modified file 'src/imports/Ubuntu/Contacts/contacts.cpp'
111--- src/imports/Ubuntu/Contacts/contacts.cpp 2015-10-14 22:53:35 +0000
112+++ src/imports/Ubuntu/Contacts/contacts.cpp 2015-10-29 18:12:58 +0000
113@@ -23,6 +23,7 @@
114 #include <QtCore/QDir>
115 #include <QtCore/QUrl>
116 #include <QtCore/QLockFile>
117+#include <QtCore/QThreadPool>
118
119 #include "config.h"
120
121@@ -77,27 +78,11 @@
122 return out;
123 }
124
125-QUrl UbuntuContacts::copyImage(QObject *contact, const QUrl &imageUrl)
126+QString UbuntuContacts::copyImage(const QUrl &imageUrl)
127 {
128- // keep track of threads to avoid memory leeak
129- ImageScaleThread *imgThread;
130- QVariant oldThread = contact->property("IMAGE_SCALE_THREAD");
131- if (!oldThread.isNull()) {
132- imgThread = oldThread.value<ImageScaleThread *>();
133- imgThread->updateImageUrl(imageUrl);
134- } else {
135- imgThread = new ImageScaleThread(imageUrl, contact);
136- contact->setProperty("IMAGE_SCALE_THREAD", QVariant::fromValue<ImageScaleThread*>(imgThread));
137- }
138-
139- imgThread->start();
140-
141- // FIXME: implement this as async function
142- while(imgThread->isRunning()) {
143- QCoreApplication::processEvents(QEventLoop::AllEvents, 3000);
144- }
145-
146- return imgThread->outputFile();
147+ ImageScaleThread *imgThread = new ImageScaleThread(imageUrl, this);
148+ QThreadPool::globalInstance()->start(imgThread);
149+ return imgThread->id();
150 }
151
152 bool UbuntuContacts::containsLetters(const QString &value)
153@@ -112,7 +97,11 @@
154
155 bool UbuntuContacts::removeFile(const QUrl &file)
156 {
157- return QFile::remove(file.toLocalFile());
158+ QString localFile = file.toLocalFile();
159+ if (!localFile.isEmpty() && QFile::exists(localFile)) {
160+ return QFile::remove(localFile);
161+ }
162+ return false;
163 }
164
165 bool UbuntuContacts::updateIsRunning() const
166
167=== modified file 'src/imports/Ubuntu/Contacts/contacts.h'
168--- src/imports/Ubuntu/Contacts/contacts.h 2015-10-13 12:50:14 +0000
169+++ src/imports/Ubuntu/Contacts/contacts.h 2015-10-29 18:12:58 +0000
170@@ -36,12 +36,13 @@
171
172 Q_INVOKABLE QString contactInitialsFromString(const QString &value);
173 Q_INVOKABLE QString normalized(const QString &value);
174- Q_INVOKABLE QUrl copyImage(QObject *contact, const QUrl &imageUrl);
175+ Q_INVOKABLE QString copyImage(const QUrl &imageUrl);
176 Q_INVOKABLE bool containsLetters(const QString &value);
177 Q_INVOKABLE bool removeFile(const QUrl &file);
178 Q_INVOKABLE bool updateIsRunning() const;
179
180 Q_SIGNALS:
181+ void imageCopyDone(const QString &id, const QString &fileName);
182 void updateIsRunningChanged();
183
184 private:
185
186=== modified file 'src/imports/Ubuntu/Contacts/imagescalethread.cpp'
187--- src/imports/Ubuntu/Contacts/imagescalethread.cpp 2015-05-07 17:27:16 +0000
188+++ src/imports/Ubuntu/Contacts/imagescalethread.cpp 2015-10-29 18:12:58 +0000
189@@ -20,39 +20,46 @@
190 #include <QImageReader>
191 #include <QFile>
192 #include <QDir>
193+#include <QUuid>
194 #include <QDebug>
195
196-ImageScaleThread::ImageScaleThread(const QUrl &imageUrl, QObject *parent)
197- : QThread(parent),
198- m_imageUrl(imageUrl),
199- m_tmpFile(0)
200+ImageScaleThread::ImageScaleThread(const QUrl &imageUrl, QObject *listener)
201+ : m_imageUrl(imageUrl),
202+ m_id(QUuid::createUuid().toString()),
203+ m_listener(listener),
204+ m_tmpFile(0)
205 {
206 }
207
208 ImageScaleThread::~ImageScaleThread()
209 {
210 if (m_tmpFile) {
211- delete m_tmpFile;
212+ m_tmpFile->setAutoRemove(false);
213+ m_tmpFile->deleteLater();
214+ m_tmpFile = 0;
215 }
216 }
217
218-void ImageScaleThread::updateImageUrl(const QUrl &imageUrl)
219+QString ImageScaleThread::id()
220 {
221- if (isRunning()) {
222- wait();
223- }
224- m_imageUrl = imageUrl;
225+ return m_id;
226 }
227
228 QString ImageScaleThread::outputFile() const
229 {
230- return m_tmpFile->fileName();
231+ if (m_tmpFile) {
232+ return m_tmpFile->fileName();
233+ } else {
234+ return QString();
235+ }
236 }
237
238 void ImageScaleThread::run()
239 {
240 // make sure that the old image get deleted
241 if (m_tmpFile) {
242+ qDebug() << "Delete previous avatar" << m_tmpFile->fileName();
243+ m_tmpFile->setAutoRemove(true);
244 m_tmpFile->close();
245 delete m_tmpFile;
246 }
247@@ -60,6 +67,7 @@
248 // Create the temporary file
249 m_tmpFile = new QTemporaryFile(QString("%1/avatar_XXXXXX.png").arg(QDir::tempPath()));
250 if (!m_tmpFile->open()) {
251+ qWarning() << "Fail to create avatar temporary file";
252 return;
253 }
254
255@@ -91,5 +99,11 @@
256 if (!scaledAvatar.isNull()) {
257 scaledAvatar.save(m_tmpFile, "png");
258 }
259+
260 m_tmpFile->close();
261+
262+ if (m_listener) {
263+ QMetaObject::invokeMethod(m_listener, "imageCopyDone",
264+ Q_ARG(QString, m_id), Q_ARG(QString, m_tmpFile->fileName()));
265+ }
266 }
267
268=== modified file 'src/imports/Ubuntu/Contacts/imagescalethread.h'
269--- src/imports/Ubuntu/Contacts/imagescalethread.h 2015-05-07 17:27:16 +0000
270+++ src/imports/Ubuntu/Contacts/imagescalethread.h 2015-10-29 18:12:58 +0000
271@@ -18,18 +18,18 @@
272 #define IMAGESCALETHREAD_H
273
274 #include <QObject>
275-#include <QThread>
276+#include <QRunnable>
277 #include <QUrl>
278+#include <QPointer>
279 #include <QTemporaryFile>
280
281-class ImageScaleThread : public QThread
282+class ImageScaleThread : public QRunnable
283 {
284- Q_OBJECT
285 public:
286- ImageScaleThread(const QUrl &imageUrl, QObject *parent=0);
287+ ImageScaleThread(const QUrl &imageUrl, QObject *listener);
288 ~ImageScaleThread();
289
290- void updateImageUrl(const QUrl &imageUrl);
291+ QString id();
292 QString outputFile() const;
293
294 protected:
295@@ -37,6 +37,8 @@
296
297 private:
298 QUrl m_imageUrl;
299+ QString m_id;
300+ QPointer<QObject> m_listener;
301 QTemporaryFile *m_tmpFile;
302 };
303
304
305=== modified file 'tests/autopilot/address_book_app/__init__.py'
306--- tests/autopilot/address_book_app/__init__.py 2015-10-20 03:38:07 +0000
307+++ tests/autopilot/address_book_app/__init__.py 2015-10-29 18:12:58 +0000
308@@ -70,7 +70,8 @@
309 def get_contact_edit_page(self):
310 # We can have two contact editor page because of bottom edge page
311 # but we will return only the active one
312- return self.wait_select_single(objectName="contactEditorPage", active=True)
313+ return self.wait_select_single(pages.ABContactEditorPage,
314+ objectName="contactEditorPage", active=True)
315
316 def get_contact_view_page(self):
317 return self.wait_select_single(pages.ABContactViewPage,
318
319=== modified file 'tests/autopilot/address_book_app/pages/__init__.py'
320--- tests/autopilot/address_book_app/pages/__init__.py 2015-05-11 14:21:03 +0000
321+++ tests/autopilot/address_book_app/pages/__init__.py 2015-10-29 18:12:58 +0000
322@@ -20,7 +20,6 @@
323 'ABContactViewPage'
324 ]
325
326-from address_book_app.address_book \
327- import ContactEditorPage as ABContactEditorPage
328+from address_book_app.pages._ab_contact_editor_page import ABContactEditorPage
329 from address_book_app.pages._ab_contact_view_page import ABContactViewPage
330 from address_book_app.pages._ab_contact_list_page import ABContactListPage
331
332=== added file 'tests/autopilot/address_book_app/pages/_ab_contact_editor_page.py'
333--- tests/autopilot/address_book_app/pages/_ab_contact_editor_page.py 1970-01-01 00:00:00 +0000
334+++ tests/autopilot/address_book_app/pages/_ab_contact_editor_page.py 2015-10-29 18:12:58 +0000
335@@ -0,0 +1,28 @@
336+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
337+#
338+# Copyright (C) 2014 Canonical Ltd.
339+#
340+# This program is free software; you can redistribute it and/or modify
341+# it under the terms of the GNU General Public License version 3, as published
342+# by the Free Software Foundation.
343+#
344+# This program is distributed in the hope that it will be useful,
345+# but WITHOUT ANY WARRANTY; without even the implied warranty of
346+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
347+# GNU General Public License for more details.
348+#
349+# You should have received a copy of the GNU General Public License
350+# along with this program. If not, see <http://www.gnu.org/licenses/>.
351+
352+""" ContactEditorPage emulator for Addressbook App tests """
353+
354+import logging
355+import time
356+
357+import autopilot.logging
358+import ubuntuuitoolkit
359+
360+from address_book_app import address_book
361+
362+class ABContactEditorPage(address_book.ContactEditorPage):
363+ """Autopilot helper for the Contact Editor page."""

Subscribers

People subscribed via source and target branches