on xenial help sign in
New simplified CroppedImageMinimumSourceSize
e788d2eAlbert Astals Cid
plugins/Dash/CMakeLists.txt−2
@@ -24,8 +24,6 @@ set(QMLPLUGIN_SRC
24 verticaljournal.cpp
24 verticaljournal.cpp
25 horizontaljournal.cpp
25 horizontaljournal.cpp
26 organicgrid.cpp
26 organicgrid.cpp
27− croppedimagesizer.cpp
28− croppedimagesizerasyncworker.cpp
29 )
27 )
30
28
31add_library(Dash-qml MODULE
29add_library(Dash-qml MODULE
plugins/Dash/CardCreator.js+4−4
@@ -68,7 +68,7 @@ var kArtShapeHolderCode = 'Item { \n\
68 objectName: "artShape"; \n\
68 objectName: "artShape"; \n\
69 property bool doShapeItem: components["art"]["conciergeMode"] !== true; \n\
69 property bool doShapeItem: components["art"]["conciergeMode"] !== true; \n\
70 visible: image.status == Image.Ready; \n\
70 visible: image.status == Image.Ready; \n\
71− readonly property alias image: artImage.image; \n\
71+ readonly property alias image: artImage; \n\
72 property alias borderSource: artShapeShape.borderSource; \n\
72 property alias borderSource: artShapeShape.borderSource; \n\
73 ShaderEffectSource { \n\
73 ShaderEffectSource { \n\
74 id: artShapeSource; \n\
74 id: artShapeSource; \n\
@@ -195,11 +195,11 @@ var kMascotShapeLoaderCode = 'Loader { \n\
195 id: mascotShapeLoader; \n\
195 id: mascotShapeLoader; \n\
196 objectName: "mascotShapeLoader"; \n\
196 objectName: "mascotShapeLoader"; \n\
197 asynchronous: root.asynchronous; \n\
197 asynchronous: root.asynchronous; \n\
198− active: mascotImage.image.status === Image.Ready; \n\
198+ active: mascotImage.status === Image.Ready; \n\
199 visible: showHeader && active && status == Loader.Ready; \n\
199 visible: showHeader && active && status == Loader.Ready; \n\
200 width: units.gu(6); \n\
200 width: units.gu(6); \n\
201 height: units.gu(5.625); \n\
201 height: units.gu(5.625); \n\
202− sourceComponent: UbuntuShape { image: mascotImage.image } \n\
202+ sourceComponent: UbuntuShape { image: mascotImage } \n\
203 anchors { %1 } \n\
203 anchors { %1 } \n\
204 }\n';
204 }\n';
205
205
@@ -476,7 +476,7 @@ function cardString(template, components) {
476 mascotCode = kMascotImageCode.arg(mascotAnchors).arg(mascotImageVisible);
476 mascotCode = kMascotImageCode.arg(mascotAnchors).arg(mascotImageVisible);
477 var fallback = components["mascot"] && components["mascot"]["fallback"] || "";
477 var fallback = components["mascot"] && components["mascot"]["fallback"] || "";
478 if (fallback !== "") {
478 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);
480 }
480 }
481 }
481 }
482
482
plugins/Dash/CroppedImageMinimumSourceSize.qml+5−22
@@ -15,30 +15,13 @@
15 */
15 */
16
16
17import QtQuick 2.3
17import QtQuick 2.3
18−import Dash 0.1
19
18
20−Item {
19+Image {
21 id: root
20 id: root
22
21
23− property string source
22+ fillMode: Image.PreserveAspectCrop
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
29
23
30− CroppedImageSizer {
24+ readonly property real itemAspectRatio: width / height
31− id: sizer
25+ readonly property real imageAspectRatio: implicitWidth / implicitHeight
32− source: root.source
26+ sourceSize: (imageAspectRatio > itemAspectRatio) ? Qt.size(0, height) : Qt.size(width, 0)
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− }
44}
27}
plugins/Dash/Dash.qmltypes−15
@@ -19,21 +19,6 @@ Module {
19 Property { name: "displayMarginBeginning"; type: "double" }
19 Property { name: "displayMarginBeginning"; type: "double" }
20 Property { name: "displayMarginEnd"; type: "double" }
20 Property { name: "displayMarginEnd"; type: "double" }
21 }
21 }
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− }
37 Component {
22 Component {
38 name: "HorizontalJournal"
23 name: "HorizontalJournal"
39 defaultProperty: "data"
24 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 @@
17
17
18#include "plugin.h"
18#include "plugin.h"
19
19
20−#include "croppedimagesizer.h"
21#include "horizontaljournal.h"
20#include "horizontaljournal.h"
22#include "listviewwithpageheader.h"
21#include "listviewwithpageheader.h"
23#include "organicgrid.h"
22#include "organicgrid.h"
@@ -33,5 +32,4 @@ void DashPlugin::registerTypes(const char *uri)
33 qmlRegisterType<ListViewWithPageHeader>(uri, 0, 1, "ListViewWithPageHeader");
32 qmlRegisterType<ListViewWithPageHeader>(uri, 0, 1, "ListViewWithPageHeader");
34 qmlRegisterType<OrganicGrid>(uri, 0, 1, "OrganicGrid");
33 qmlRegisterType<OrganicGrid>(uri, 0, 1, "OrganicGrid");
35 qmlRegisterType<VerticalJournal>(uri, 0, 1, "VerticalJournal");
34 qmlRegisterType<VerticalJournal>(uri, 0, 1, "VerticalJournal");
36− qmlRegisterType<CroppedImageSizer>(uri, 0, 1, "CroppedImageSizer");
37}
35}
tests/plugins/Dash/cardcreator/1.res+1−1
@@ -32,7 +32,7 @@ Item {
32 objectName: "artShape";
32 objectName: "artShape";
33 property bool doShapeItem: components["art"]["conciergeMode"] !== true;
33 property bool doShapeItem: components["art"]["conciergeMode"] !== true;
34 visible: image.status == Image.Ready;
34 visible: image.status == Image.Ready;
35− readonly property alias image: artImage.image;
35+ readonly property alias image: artImage;
36 property alias borderSource: artShapeShape.borderSource;
36 property alias borderSource: artShapeShape.borderSource;
37 ShaderEffectSource {
37 ShaderEffectSource {
38 id: artShapeSource;
38 id: artShapeSource;
tests/plugins/Dash/cardcreator/3.res+1−1
@@ -32,7 +32,7 @@ Item {
32 objectName: "artShape";
32 objectName: "artShape";
33 property bool doShapeItem: components["art"]["conciergeMode"] !== true;
33 property bool doShapeItem: components["art"]["conciergeMode"] !== true;
34 visible: image.status == Image.Ready;
34 visible: image.status == Image.Ready;
35− readonly property alias image: artImage.image;
35+ readonly property alias image: artImage;
36 property alias borderSource: artShapeShape.borderSource;
36 property alias borderSource: artShapeShape.borderSource;
37 ShaderEffectSource {
37 ShaderEffectSource {
38 id: artShapeSource;
38 id: artShapeSource;
tests/plugins/Dash/cardcreator/4.res+2−2
@@ -34,11 +34,11 @@ Loader {
34 id: mascotShapeLoader;
34 id: mascotShapeLoader;
35 objectName: "mascotShapeLoader";
35 objectName: "mascotShapeLoader";
36 asynchronous: root.asynchronous;
36 asynchronous: root.asynchronous;
37− active: mascotImage.image.status === Image.Ready;
37+ active: mascotImage.status === Image.Ready;
38 visible: showHeader && active && status == Loader.Ready;
38 visible: showHeader && active && status == Loader.Ready;
39 width: units.gu(6);
39 width: units.gu(6);
40 height: units.gu(5.625);
40 height: units.gu(5.625);
41− sourceComponent: UbuntuShape { image: mascotImage.image }
41+ sourceComponent: UbuntuShape { image: mascotImage }
42 anchors { verticalCenter: parent.verticalCenter; }
42 anchors { verticalCenter: parent.verticalCenter; }
43 }
43 }
44
44
tests/plugins/Dash/cardcreator/5.res+1−1
@@ -32,7 +32,7 @@ Item {
32 objectName: "artShape";
32 objectName: "artShape";
33 property bool doShapeItem: components["art"]["conciergeMode"] !== true;
33 property bool doShapeItem: components["art"]["conciergeMode"] !== true;
34 visible: image.status == Image.Ready;
34 visible: image.status == Image.Ready;
35− readonly property alias image: artImage.image;
35+ readonly property alias image: artImage;
36 property alias borderSource: artShapeShape.borderSource;
36 property alias borderSource: artShapeShape.borderSource;
37 ShaderEffectSource {
37 ShaderEffectSource {
38 id: artShapeSource;
38 id: artShapeSource;
tests/plugins/Dash/tst_CroppedImageMinimumSourceSize.qml+6−6
@@ -41,16 +41,16 @@ Rectangle {
41 when: windowShown
41 when: windowShown
42
42
43 function test_croppedSource() {
43 function test_croppedSource() {
44− tryCompare(cimss.image.sourceSize, "width", 100);
44+ tryCompare(cimss.sourceSize, "width", 100);
45− tryCompare(cimss.image.sourceSize, "height", 0);
45+ tryCompare(cimss.sourceSize, "height", 0);
46
46
47 cimss.width = 40;
47 cimss.width = 40;
48− tryCompare(cimss.image.sourceSize, "width", 0);
48+ tryCompare(cimss.sourceSize, "width", 0);
49− tryCompare(cimss.image.sourceSize, "height", 100);
49+ tryCompare(cimss.sourceSize, "height", 100);
50
50
51 cimss.width = 100;
51 cimss.width = 100;
52− tryCompare(cimss.image.sourceSize, "width", 100);
52+ tryCompare(cimss.sourceSize, "width", 100);
53− tryCompare(cimss.image.sourceSize, "height", 0);
53+ tryCompare(cimss.sourceSize, "height", 0);
54 }
54 }
55 }
55 }
56}
56}