on xenial help sign in
Try to use QImageReader not to load the image into memory twice
ee61f43Albert Astals
plugins/Dash/CMakeLists.txt+1
@@ -25,6 +25,7 @@ set(QMLPLUGIN_SRC
25 verticaljournal.cpp
25 verticaljournal.cpp
26 horizontaljournal.cpp
26 horizontaljournal.cpp
27 organicgrid.cpp
27 organicgrid.cpp
28+ croppedimagesizer.cpp
28 )
29 )
29
30
30add_library(Dash-qml MODULE
31add_library(Dash-qml MODULE
plugins/Dash/CardCreator.js+6−5
@@ -82,16 +82,17 @@ var kArtShapeHolderCode = 'Item { \n\
82 height = Qt.binding(function() { return image.status !== Image.Ready ? 0 : image.height }); \n\
82 height = Qt.binding(function() { return image.status !== Image.Ready ? 0 : image.height }); \n\
83 } \n\
83 } \n\
84 } \n\
84 } \n\
85− image: CroppedImageMinimumSourceSize { \n\
85+ CroppedImageMinimumSourceSize { \n\
86+ id: artImage; \n\
86 objectName: "artImage"; \n\
87 objectName: "artImage"; \n\
87 property bool doLoadSource: !NetworkingStatus.limitedBandwith; \n\
88 property bool doLoadSource: !NetworkingStatus.limitedBandwith; \n\
88 source: { if (root.visible) doLoadSource = true; return doLoadSource && cardData && cardData["art"] || ""; } \n\
89 source: { if (root.visible) doLoadSource = true; return doLoadSource && cardData && cardData["art"] || ""; } \n\
89− cache: true; \n\
90 asynchronous: root.asynchronous; \n\
90 asynchronous: root.asynchronous; \n\
91 visible: false; \n\
91 visible: false; \n\
92 width: %2; \n\
92 width: %2; \n\
93 height: %3; \n\
93 height: %3; \n\
94 } \n\
94 } \n\
95+ image: artImage.image; \n\
95 } \n\
96 } \n\
96 } \n\
97 } \n\
97 }\n';
98 }\n';
@@ -181,11 +182,11 @@ var kMascotShapeLoaderCode = 'Loader { \n\
181 id: mascotShapeLoader; \n\
182 id: mascotShapeLoader; \n\
182 objectName: "mascotShapeLoader"; \n\
183 objectName: "mascotShapeLoader"; \n\
183 asynchronous: root.asynchronous; \n\
184 asynchronous: root.asynchronous; \n\
184− active: mascotImage.status === Image.Ready; \n\
185+ active: mascotImage.image.status === Image.Ready; \n\
185 visible: showHeader && active && status == Loader.Ready; \n\
186 visible: showHeader && active && status == Loader.Ready; \n\
186 width: units.gu(6); \n\
187 width: units.gu(6); \n\
187 height: units.gu(5.625); \n\
188 height: units.gu(5.625); \n\
188− sourceComponent: UbuntuShape { image: mascotImage } \n\
189+ sourceComponent: UbuntuShape { image: mascotImage.image } \n\
189 anchors { %1 } \n\
190 anchors { %1 } \n\
190 }\n';
191 }\n';
191
192
@@ -433,7 +434,7 @@ function cardString(template, components) {
433 mascotShapeCode = kMascotShapeLoaderCode.arg(mascotAnchors);
434 mascotShapeCode = kMascotShapeLoaderCode.arg(mascotAnchors);
434 }
435 }
435
436
436− var mascotImageVisible = useMascotShape ? 'false' : 'showHeader && resized';
437+ var mascotImageVisible = useMascotShape ? 'false' : 'showHeader';
437 mascotCode = kMascotImageCode.arg(mascotAnchors).arg(mascotImageVisible);
438 mascotCode = kMascotImageCode.arg(mascotAnchors).arg(mascotImageVisible);
438 }
439 }
439
440
plugins/Dash/CroppedImageMinimumSourceSize.qml+24−18
@@ -15,24 +15,30 @@
15 */
15 */
16
16
17import QtQuick 2.3
17import QtQuick 2.3
18+import Dash 0.1
18
19
19−Image {
20+Item {
20− property bool resized: false
21+ id: root
21− property bool resizing: false
22+
23+ property alias image: image
24+ property string source
25+ property alias asynchronous: image.asynchronous
26+ property alias verticalAlignment: image.verticalAlignment
27+ property alias horizontalAlignment: image.horizontalAlignment
28+
29+ CroppedImageSizer
30+ {
31+ id: sizer
32+ source: root.source
33+ width: root.width
34+ height: root.height
35+ }
36+
37+ Image {
38+ id: image
39+ anchors.fill: parent
22− fillMode: Image.PreserveAspectCrop
40+ fillMode: Image.PreserveAspectCrop
23− visible: resized
41+ sourceSize: sizer.sourceSize.width == 0 && sizer.sourceSize.height == 0 ? undefined : sizer.sourceSize
24− onSourceSizeChanged: {
25− if (!resized && !resizing) {
26− resizing = true;
27− var ar = width / height;
28− var ssar = sourceSize.width / sourceSize.height;
42+ source: sourceSize.width == -1 && sourceSize.height == -1 ? "" : root.source
29− if (ar > ssar) {
30− sourceSize = Qt.size(width, 0);
31− } else {
32− sourceSize = Qt.size(0, height);
33− }
34− resizing = false;
35− resized = true;
36− }
37 }
43 }
38}
44}
plugins/Dash/croppedimagesizer.cppnew file+115
@@ -0,0 +1,115 @@
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 <QDebug>
20+#include <QNetworkReply>
21+#include <QNetworkRequest>
22+#include <QQmlEngine>
23+#include <QQuickItem>
24+#include <QQuickView>
25+
26+CroppedImageSizer::CroppedImageSizer()
27+{
28+ connect(this, &CroppedImageSizer::inputParamsChanged, this, &CroppedImageSizer::calculateSourceSize);
29+}
30+
31+CroppedImageSizer::~CroppedImageSizer()
32+{
33+ if (m_reply) {
34+ m_reply->deleteLater();
35+ }
36+}
37+
38+QUrl CroppedImageSizer::source() const
39+{
40+ return m_source;
41+}
42+
43+void CroppedImageSizer::setSource(const QUrl &source)
44+{
45+ if (source != m_source) {
46+ m_source = source;
47+ Q_EMIT inputParamsChanged();
48+ }
49+}
50+
51+qreal CroppedImageSizer::width() const
52+{
53+ return m_width;
54+}
55+
56+void CroppedImageSizer::setWidth(qreal width)
57+{
58+ if (width != m_width) {
59+ m_width = width;
60+ Q_EMIT inputParamsChanged();
61+ }
62+}
63+
64+qreal CroppedImageSizer::height() const
65+{
66+ return m_height;
67+}
68+
69+void CroppedImageSizer::setHeight(qreal height)
70+{
71+ if (height != m_height) {
72+ m_height = height;
73+ Q_EMIT inputParamsChanged();
74+ }
75+}
76+
77+QSize CroppedImageSizer::sourceSize() const
78+{
79+ return m_sourceSize;
80+}
81+
82+void CroppedImageSizer::calculateSourceSize()
83+{
84+ if (m_source.isValid() && m_width > 0 && m_height > 0 && qmlEngine(this) && qmlEngine(this)->networkAccessManager()) {
85+ if (m_reply) {
86+ m_reply->abort();
87+ m_reply->deleteLater();
88+ }
89+ QNetworkRequest request(m_source);
90+ m_reply = qmlEngine(this)->networkAccessManager()->get(request);
91+ connect(m_reply, &QNetworkReply::finished, this, &CroppedImageSizer::requestFinished);
92+ }
93+}
94+
95+void CroppedImageSizer::requestFinished()
96+{
97+ QImageReader m_reader(m_reply);
98+ const QSize imageSize = m_reader.size();
99+ if (imageSize.isValid()) {
100+ const qreal ar = width() / height();
101+ const qreal ssar = imageSize.width() / imageSize.height();
102+ if (ar > ssar) {
103+ m_sourceSize = QSize(m_width, 0);
104+ } else {
105+ m_sourceSize = QSize(0, m_height);
106+ }
107+ } else {
108+ qWarning() << "Could not find size of" << m_source;
109+ m_sourceSize = QSize(0, 0);
110+ }
111+ sourceSizeChanged();
112+
113+ m_reply->deleteLater();
114+ m_reply = nullptr;
115+}
plugins/Dash/croppedimagesizer.hnew file+67
@@ -0,0 +1,67 @@
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 QNetworkReply;
26+
27+class CroppedImageSizer : public QObject
28+{
29+ Q_OBJECT
30+
31+ Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY inputParamsChanged)
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+
51+Q_SIGNALS:
52+ void inputParamsChanged();
53+ void sourceSizeChanged();
54+
55+private Q_SLOT:
56+ void calculateSourceSize();
57+ void requestFinished();
58+
59+private:
60+ QUrl m_source;
61+ qreal m_width = 0;
62+ qreal m_height = 0;
63+ QSize m_sourceSize = QSize(-1, -1);
64+ QNetworkReply *m_reply = nullptr;
65+};
66+
67+#endif
plugins/Dash/plugin.cpp+2
@@ -17,6 +17,7 @@
17
17
18#include "plugin.h"
18#include "plugin.h"
19
19
20+#include "croppedimagesizer.h"
20#include "horizontaljournal.h"
21#include "horizontaljournal.h"
21#include "listviewwithpageheader.h"
22#include "listviewwithpageheader.h"
22#include "organicgrid.h"
23#include "organicgrid.h"
@@ -32,4 +33,5 @@ void DashPlugin::registerTypes(const char *uri)
32 qmlRegisterType<ListViewWithPageHeader>(uri, 0, 1, "ListViewWithPageHeader");
33 qmlRegisterType<ListViewWithPageHeader>(uri, 0, 1, "ListViewWithPageHeader");
33 qmlRegisterType<OrganicGrid>(uri, 0, 1, "OrganicGrid");
34 qmlRegisterType<OrganicGrid>(uri, 0, 1, "OrganicGrid");
34 qmlRegisterType<VerticalJournal>(uri, 0, 1, "VerticalJournal");
35 qmlRegisterType<VerticalJournal>(uri, 0, 1, "VerticalJournal");
36+ qmlRegisterType<CroppedImageSizer>(uri, 0, 1, "CroppedImageSizer");
35}
37}
tests/plugins/Dash/CMakeLists.txt+2
@@ -73,6 +73,8 @@ qt5_use_modules(CardCreatorTestExec Test Core Qml)
73target_link_libraries(CardCreatorTestExec ${Qt5Gui_LIBRARIES} ${Qt5Quick_LIBRARIES})
73target_link_libraries(CardCreatorTestExec ${Qt5Gui_LIBRARIES} ${Qt5Quick_LIBRARIES})
74add_binary_qml_test(CardCreator "" "Dash-qml" "QML2_IMPORT_PATH=${CMAKE_BINARY_DIR}/tests/mocks/")
74add_binary_qml_test(CardCreator "" "Dash-qml" "QML2_IMPORT_PATH=${CMAKE_BINARY_DIR}/tests/mocks/")
75
75
76+add_qml_test(. CroppedImageMinimumSourceSize IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins)
77+
76# plain qml test
78# plain qml test
77set(qmltest_DEFAULT_TARGETS qmluitests)
79set(qmltest_DEFAULT_TARGETS qmluitests)
78set(qmltest_DEFAULT_NO_ADD_TEST TRUE)
80set(qmltest_DEFAULT_NO_ADD_TEST TRUE)
tests/plugins/Dash/tst_CroppedImageMinimumSourceSize.qmlnew file+28
@@ -0,0 +1,28 @@
1+
2+import QtQuick 2.3
3+import Ubuntu.Components 1.1
4+import Dash 0.1
5+
6+Rectangle {
7+ width: 500
8+ height: 300
9+
10+ color: "red"
11+
12+ CroppedImageMinimumSourceSize {
13+ x: 100
14+ y: 100
15+ width: 100
16+ height: 100
17+ source: Qt.resolvedUrl("../../qmltests/Dash/artwork/avatar.png")
18+ }
19+
20+ CroppedImageMinimumSourceSize {
21+ x: 300
22+ y: 100
23+ width: 100
24+ height: 100
25+ source: "http://assets.ubuntu.com/sites/ubuntu/latest/u/img/homepage/1410/1410-wallpaper.jpg"
26+ }
27+}
28+