on xenial help sign in
New simplified CroppedImageMinimumSourceSize

There's only two sizes we need to ask, so ask one and if it's not the good, ask the other Benefits over the old one: * Much less code * If we're lucky we just ask for the image once * Works on all image urls Fixes: #1467740 Approved by: Michał Sawicz

commite788d2e8d39d7513ac6fbb3ee18ed125e528e053 authorAlbert Astals Cid <albert.astals@canonical.com> dateTue 15 Sep 2015, 12:04 (11 years ago) parent00977391a09225
14 files changed+20−385
plugins/Dash/CMakeLists.txt−2 plugins/Dash/CardCreator.js+4−4 plugins/Dash/CroppedImageMinimumSourceSize.qml+5−22 plugins/Dash/Dash.qmltypes−15 plugins/Dash/croppedimagesizer.cpp−136 plugins/Dash/croppedimagesizer.h−72 plugins/Dash/croppedimagesizerasyncworker.cpp−74 plugins/Dash/croppedimagesizerasyncworker.h−47 plugins/Dash/plugin.cpp−2 tests/plugins/Dash/cardcreator/1.res+1−1 tests/plugins/Dash/cardcreator/3.res+1−1 tests/plugins/Dash/cardcreator/4.res+2−2 tests/plugins/Dash/cardcreator/5.res+1−1 tests/plugins/Dash/tst_CroppedImageMinimumSourceSize.qml+6−6
plugins/Dash/CMakeLists.txt−2
@@ -24,8 +24,6 @@ set(QMLPLUGIN_SRC
2424 verticaljournal.cpp
2525 horizontaljournal.cpp
2626 organicgrid.cpp
27− croppedimagesizer.cpp
28− croppedimagesizerasyncworker.cpp
2927 )
3028
3129add_library(Dash-qml MODULE
plugins/Dash/CardCreator.js+4−4
@@ -68,7 +68,7 @@ var kArtShapeHolderCode = 'Item { \n\
6868 objectName: "artShape"; \n\
6969 property bool doShapeItem: components["art"]["conciergeMode"] !== true; \n\
7070 visible: image.status == Image.Ready; \n\
71− readonly property alias image: artImage.image; \n\
71+ readonly property alias image: artImage; \n\
7272 property alias borderSource: artShapeShape.borderSource; \n\
7373 ShaderEffectSource { \n\
7474 id: artShapeSource; \n\
@@ -195,11 +195,11 @@ var kMascotShapeLoaderCode = 'Loader { \n\
195195 id: mascotShapeLoader; \n\
196196 objectName: "mascotShapeLoader"; \n\
197197 asynchronous: root.asynchronous; \n\
198− active: mascotImage.image.status === Image.Ready; \n\
198+ active: mascotImage.status === Image.Ready; \n\
199199 visible: showHeader && active && status == Loader.Ready; \n\
200200 width: units.gu(6); \n\
201201 height: units.gu(5.625); \n\
202− sourceComponent: UbuntuShape { image: mascotImage.image } \n\
202+ sourceComponent: UbuntuShape { image: mascotImage } \n\
203203 anchors { %1 } \n\
204204 }\n';
205205
@@ -476,7 +476,7 @@ function cardString(template, components) {
476476 mascotCode = kMascotImageCode.arg(mascotAnchors).arg(mascotImageVisible);
477477 var fallback = components["mascot"] && components["mascot"]["fallback"] || "";
478478 if (fallback !== "") {
479− code += 'Connections { target: mascotImage.image; onStatusChanged: if (mascotImage.image.status === Image.Error) mascotImage.source = "%1"; } \n'.arg(fallback);
479+ code += 'Connections { target: mascotImage; onStatusChanged: if (mascotImage.status === Image.Error) mascotImage.source = "%1"; } \n'.arg(fallback);
480480 }
481481 }
482482
plugins/Dash/CroppedImageMinimumSourceSize.qml+5−22
@@ -15,30 +15,13 @@
1515 */
1616
1717import QtQuick 2.3
18−import Dash 0.1
1918
20−Item {
19+Image {
2120 id: root
2221
23− property string source
24− property alias image: innerImage
25− property alias asynchronous: innerImage.asynchronous
26− property alias verticalAlignment: innerImage.verticalAlignment
27− property alias horizontalAlignment: innerImage.horizontalAlignment
28− property alias fillMode: innerImage.fillMode
22+ fillMode: Image.PreserveAspectCrop
2923
30− CroppedImageSizer {
31− id: sizer
32− source: root.source
33− width: root.width
34− height: root.height
35− }
36−
37− Image {
38− id: innerImage
39− anchors.fill: parent
40− fillMode: Image.PreserveAspectCrop
41− sourceSize: sizer.sourceSize.width == 0 && sizer.sourceSize.height == 0 ? undefined : sizer.sourceSize
42− source: sizer.sourceSize.width == -1 && sizer.sourceSize.height == -1 ? "" : root.source
43− }
24+ readonly property real itemAspectRatio: width / height
25+ readonly property real imageAspectRatio: implicitWidth / implicitHeight
26+ sourceSize: (imageAspectRatio > itemAspectRatio) ? Qt.size(0, height) : Qt.size(width, 0)
4427}
plugins/Dash/Dash.qmltypes−15
@@ -19,21 +19,6 @@ Module {
1919 Property { name: "displayMarginBeginning"; type: "double" }
2020 Property { name: "displayMarginEnd"; type: "double" }
2121 }
22− Component {
23− name: "CroppedImageSizer"
24− prototype: "QObject"
25− exports: ["Dash/CroppedImageSizer 0.1"]
26− exportMetaObjectRevisions: [0]
27− Property { name: "source"; type: "QUrl" }
28− Property { name: "width"; type: "double" }
29− Property { name: "height"; type: "double" }
30− Property { name: "sourceSize"; type: "QSize"; isReadonly: true }
31− Signal { name: "inputParamsChanged" }
32− Method {
33− name: "setImageSize"
34− Parameter { name: "imageSize"; type: "QSize" }
35− }
36− }
3722 Component {
3823 name: "HorizontalJournal"
3924 defaultProperty: "data"
plugins/Dash/croppedimagesizer.cppdeleted−136
@@ -1,136 +0,0 @@
1−/*
2− * Copyright (C) 2014 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#include "croppedimagesizer.h"
18−
19−#include "croppedimagesizerasyncworker.h"
20−
21−#include <QNetworkAccessManager>
22−#include <QNetworkRequest>
23−#include <QQmlEngine>
24−#include <QQuickItem>
25−
26−CroppedImageSizer::CroppedImageSizer()
27− : m_width(0),
28− m_height(0),
29− m_sourceSize(QSize(-1, -1)),
30− m_worker(nullptr)
31−{
32− connect(this, &CroppedImageSizer::inputParamsChanged, this, &CroppedImageSizer::calculateSourceSize);
33− connect(this, &CroppedImageSizer::sourceChanged, this, &CroppedImageSizer::requestImage);
34−}
35−
36−CroppedImageSizer::~CroppedImageSizer()
37−{
38− if (m_worker) {
39− m_worker->abort();
40− }
41−}
42−
43−QUrl CroppedImageSizer::source() const
44−{
45− return m_source;
46−}
47−
48−void CroppedImageSizer::setSource(const QUrl &source)
49−{
50− if (source != m_source) {
51− m_source = source;
52− Q_EMIT sourceChanged();
53− }
54−}
55−
56−qreal CroppedImageSizer::width() const
57−{
58− return m_width;
59−}
60−
61−void CroppedImageSizer::setWidth(qreal width)
62−{
63− if (width != m_width) {
64− m_width = width;
65− Q_EMIT inputParamsChanged();
66− }
67−}
68−
69−qreal CroppedImageSizer::height() const
70−{
71− return m_height;
72−}
73−
74−void CroppedImageSizer::setHeight(qreal height)
75−{
76− if (height != m_height) {
77− m_height = height;
78− Q_EMIT inputParamsChanged();
79− }
80−}
81−
82−QSize CroppedImageSizer::sourceSize() const
83−{
84− return m_sourceSize;
85−}
86−
87−void CroppedImageSizer::setSourceSize(const QSize &sourceSize)
88−{
89− if (sourceSize != m_sourceSize) {
90− m_sourceSize = sourceSize;
91− Q_EMIT sourceSizeChanged();
92− }
93−}
94−
95−void CroppedImageSizer::setImageSize(const QSize &imageSize)
96−{
97− m_imageSize = imageSize;
98− m_worker = nullptr;
99− calculateSourceSize();
100−}
101−
102−void CroppedImageSizer::requestImage()
103−{
104− if (m_worker) {
105− m_worker->abort();
106− m_worker = nullptr;
107− }
108−
109− if (m_source.isValid() && qmlEngine(this) && qmlEngine(this)->networkAccessManager()) {
110− QNetworkRequest request(m_source);
111− QNetworkReply *reply = qmlEngine(this)->networkAccessManager()->get(request);
112− m_worker = new CroppedImageSizerAsyncWorker(this, reply);
113− } else {
114− setSourceSize(QSize(-1, -1));
115− }
116−}
117−
118−void CroppedImageSizer::calculateSourceSize()
119−{
120− if (m_source.isValid() && m_width > 0 && m_height > 0 && !m_worker) {
121− if (!m_imageSize.isEmpty()) {
122− const qreal ar = m_width / m_height;
123− const qreal ssar = m_imageSize.width() / (qreal)m_imageSize.height();
124− if (ar > ssar) {
125− setSourceSize(QSize(m_width, 0));
126− } else {
127− setSourceSize(QSize(0, m_height));
128− }
129− } else {
130− qWarning() << "Invalid size for " << m_source << m_imageSize;
131− setSourceSize(QSize(0, 0));
132− }
133− } else {
134− setSourceSize(QSize(-1, -1));
135− }
136−}
plugins/Dash/croppedimagesizer.hdeleted−72
@@ -1,72 +0,0 @@
1−/*
2− * Copyright (C) 2014 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#ifndef CROPPEDIMAGESIZER_H
18−#define CROPPEDIMAGESIZER_H
19−
20−#include <QImageReader>
21−#include <QObject>
22−#include <QSize>
23−#include <QUrl>
24−
25−class CroppedImageSizerAsyncWorker;
26−
27−class CroppedImageSizer : public QObject
28−{
29− Q_OBJECT
30−
31− Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
32− Q_PROPERTY(qreal width READ width WRITE setWidth NOTIFY inputParamsChanged)
33− Q_PROPERTY(qreal height READ height WRITE setHeight NOTIFY inputParamsChanged)
34− Q_PROPERTY(QSize sourceSize READ sourceSize NOTIFY sourceSizeChanged)
35−
36−public:
37− CroppedImageSizer();
38− ~CroppedImageSizer();
39−
40− QUrl source() const;
41− void setSource(const QUrl &source);
42−
43− qreal width() const;
44− void setWidth(qreal width);
45−
46− qreal height() const;
47− void setHeight(qreal height);
48−
49− QSize sourceSize() const;
50− void setSourceSize(const QSize &sourceSize);
51−
52− Q_INVOKABLE void setImageSize(const QSize &imageSize);
53−
54−Q_SIGNALS:
55− void inputParamsChanged();
56− void sourceChanged();
57− void sourceSizeChanged();
58−
59−private Q_SLOT:
60− void calculateSourceSize();
61− void requestImage();
62−
63−private:
64− QUrl m_source;
65− qreal m_width;
66− qreal m_height;
67− QSize m_sourceSize;
68− QSize m_imageSize;
69− QPointer<CroppedImageSizerAsyncWorker> m_worker;
70−};
71−
72−#endif
plugins/Dash/croppedimagesizerasyncworker.cppdeleted−74
@@ -1,74 +0,0 @@
1−/*
2− * Copyright (C) 2014 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#include "croppedimagesizerasyncworker.h"
18−
19−#include "croppedimagesizer.h"
20−
21−#include <QNetworkReply>
22−#include <QtConcurrentRun>
23−
24−CroppedImageSizerAsyncWorker::CroppedImageSizerAsyncWorker(CroppedImageSizer *sizer, QNetworkReply *reply)
25− : m_sizer(sizer),
26− m_reply(reply),
27− m_ignoreAbort(false)
28−{
29− connect(m_reply, &QNetworkReply::finished, this, &CroppedImageSizerAsyncWorker::requestFinished);
30−}
31−
32−void CroppedImageSizerAsyncWorker::abort()
33−{
34− // This runs on main thread
35− QMutexLocker locker(&m_mutex);
36− m_sizer = nullptr;
37− // If we already started the future run we can't abort the reply
38− // since we don't know at which stage the future is, just let it finish
39− if (!m_ignoreAbort) {
40− QMetaObject::invokeMethod(m_reply, "abort", Qt::QueuedConnection);
41− }
42−}
43−
44−void CroppedImageSizerAsyncWorker::requestFinished()
45−{
46− // This runs on main thread
47− QMutexLocker locker(&m_mutex);
48− if (m_sizer) {
49− m_ignoreAbort = true;
50− QtConcurrent::run(processRequestFinished, this);
51− } else {
52− // We were aborted delete ourselves
53− m_reply->deleteLater();
54− deleteLater();
55− }
56−}
57−
58−void CroppedImageSizerAsyncWorker::processRequestFinished(CroppedImageSizerAsyncWorker *worker)
59−{
60− // This runs on non main thread
61− // m_reply has finished at this point and is protected against change by m_ignoreAbort
62− QImageReader reader(worker->m_reply);
63− const QSize imageSize = reader.size();
64−
65− worker->m_mutex.lock();
66− if (worker->m_sizer) {
67− QMetaObject::invokeMethod(worker->m_sizer, "setImageSize", Qt::QueuedConnection, Q_ARG(QSize, imageSize));
68− }
69− worker->m_mutex.unlock();
70−
71− // All work is done, delete ourselves
72− worker->m_reply->deleteLater();
73− worker->deleteLater();
74−}
plugins/Dash/croppedimagesizerasyncworker.hdeleted−47
@@ -1,47 +0,0 @@
1−/*
2− * Copyright (C) 2014 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#ifndef CROPPEDIMAGESIZERASYNCWORKER_H
18−#define CROPPEDIMAGESIZERASYNCWORKER_H
19−
20−#include <QMutex>
21−#include <QObject>
22−
23−class CroppedImageSizer;
24−
25−class QNetworkReply;
26−
27−class CroppedImageSizerAsyncWorker : public QObject
28−{
29− Q_OBJECT
30−public:
31− CroppedImageSizerAsyncWorker(CroppedImageSizer *sizer, QNetworkReply *reply);
32−
33− void abort();
34−
35−private Q_SLOTS:
36− void requestFinished();
37−
38−private:
39− static void processRequestFinished(CroppedImageSizerAsyncWorker *worker);
40−
41− QMutex m_mutex;
42− CroppedImageSizer *m_sizer;
43− QNetworkReply *m_reply;
44− bool m_ignoreAbort;
45−};
46−
47−#endif
plugins/Dash/plugin.cpp−2
@@ -17,7 +17,6 @@
1717
1818#include "plugin.h"
1919
20−#include "croppedimagesizer.h"
2120#include "horizontaljournal.h"
2221#include "listviewwithpageheader.h"
2322#include "organicgrid.h"
@@ -33,5 +32,4 @@ void DashPlugin::registerTypes(const char *uri)
3332 qmlRegisterType<ListViewWithPageHeader>(uri, 0, 1, "ListViewWithPageHeader");
3433 qmlRegisterType<OrganicGrid>(uri, 0, 1, "OrganicGrid");
3534 qmlRegisterType<VerticalJournal>(uri, 0, 1, "VerticalJournal");
36− qmlRegisterType<CroppedImageSizer>(uri, 0, 1, "CroppedImageSizer");
3735}
tests/plugins/Dash/cardcreator/1.res+1−1
@@ -32,7 +32,7 @@ Item {
3232 objectName: "artShape";
3333 property bool doShapeItem: components["art"]["conciergeMode"] !== true;
3434 visible: image.status == Image.Ready;
35− readonly property alias image: artImage.image;
35+ readonly property alias image: artImage;
3636 property alias borderSource: artShapeShape.borderSource;
3737 ShaderEffectSource {
3838 id: artShapeSource;
tests/plugins/Dash/cardcreator/3.res+1−1
@@ -32,7 +32,7 @@ Item {
3232 objectName: "artShape";
3333 property bool doShapeItem: components["art"]["conciergeMode"] !== true;
3434 visible: image.status == Image.Ready;
35− readonly property alias image: artImage.image;
35+ readonly property alias image: artImage;
3636 property alias borderSource: artShapeShape.borderSource;
3737 ShaderEffectSource {
3838 id: artShapeSource;
tests/plugins/Dash/cardcreator/4.res+2−2
@@ -34,11 +34,11 @@ Loader {
3434 id: mascotShapeLoader;
3535 objectName: "mascotShapeLoader";
3636 asynchronous: root.asynchronous;
37− active: mascotImage.image.status === Image.Ready;
37+ active: mascotImage.status === Image.Ready;
3838 visible: showHeader && active && status == Loader.Ready;
3939 width: units.gu(6);
4040 height: units.gu(5.625);
41− sourceComponent: UbuntuShape { image: mascotImage.image }
41+ sourceComponent: UbuntuShape { image: mascotImage }
4242 anchors { verticalCenter: parent.verticalCenter; }
4343 }
4444
tests/plugins/Dash/cardcreator/5.res+1−1
@@ -32,7 +32,7 @@ Item {
3232 objectName: "artShape";
3333 property bool doShapeItem: components["art"]["conciergeMode"] !== true;
3434 visible: image.status == Image.Ready;
35− readonly property alias image: artImage.image;
35+ readonly property alias image: artImage;
3636 property alias borderSource: artShapeShape.borderSource;
3737 ShaderEffectSource {
3838 id: artShapeSource;
tests/plugins/Dash/tst_CroppedImageMinimumSourceSize.qml+6−6
@@ -41,16 +41,16 @@ Rectangle {
4141 when: windowShown
4242
4343 function test_croppedSource() {
44− tryCompare(cimss.image.sourceSize, "width", 100);
45− tryCompare(cimss.image.sourceSize, "height", 0);
44+ tryCompare(cimss.sourceSize, "width", 100);
45+ tryCompare(cimss.sourceSize, "height", 0);
4646
4747 cimss.width = 40;
48− tryCompare(cimss.image.sourceSize, "width", 0);
49− tryCompare(cimss.image.sourceSize, "height", 100);
48+ tryCompare(cimss.sourceSize, "width", 0);
49+ tryCompare(cimss.sourceSize, "height", 100);
5050
5151 cimss.width = 100;
52− tryCompare(cimss.image.sourceSize, "width", 100);
53− tryCompare(cimss.image.sourceSize, "height", 0);
52+ tryCompare(cimss.sourceSize, "width", 100);
53+ tryCompare(cimss.sourceSize, "height", 0);
5454 }
5555 }
5656}