on xenial help sign in
Introduce Preview.qml, along with tests.
a85cdbaMichał Sawicz
qml/Dash/Previews/Preview.qmlnew file+99
@@ -0,0 +1,99 @@
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+import QtQuick 2.0
18+import Ubuntu.Components 0.1
19+
20+/*! \brief This component constructs the Preview UI.
21+ *
22+ * Currently it displays all the widgets in a flickable column.
23+ */
24+
25+Item {
26+ id: root
27+
28+ /*! \brief Model containing preview widgets.
29+ *
30+ * The model should expose "widgetId", "type" and "properties" roles, as well as
31+ * have a triggered(QString widgetId, QString actionId, QVariantMap data) method,
32+ * that's called when actions are executed in widgets.
33+ */
34+ property var previewModel
35+
36+ //! \brief Should be set to true if this preview is currently displayed.
37+ property bool isCurrent: false
38+
39+ clip: true
40+
41+ Connections {
42+ target: shell.applicationManager
43+ onMainStageFocusedApplicationChanged: {
44+ root.close();
45+ }
46+ onSideStageFocusedApplicationChanged: {
47+ root.close();
48+ }
49+ }
50+
51+ onPreviewModelChanged: processingMouseArea = false
52+
53+ MouseArea {
54+ anchors.fill: parent
55+ }
56+
57+ Row {
58+ id: row
59+
60+ spacing: units.gu(1)
61+ anchors { fill: parent; margins: spacing }
62+
63+ Repeater {
64+ model: 1
65+
66+ delegate: ListView {
67+ id: column
68+ anchors { top: parent.top; bottom: parent.bottom }
69+ width: row.width
70+ spacing: row.spacing
71+ bottomMargin: Qt.inputMethod.visible ? Qt.inputMethod.keyboardRectangle.height : 0
72+
73+ model: previewModel
74+
75+ delegate: PreviewWidgetFactory {
76+ widgetId: model.widgetId
77+ widgetType: model.type
78+ widgetData: model.properties
79+ isCurrentPreview: root.isCurrent
80+ anchors { left: parent.left; right: parent.right }
81+
82+ onTriggered: {
83+ processingMouseArea.enabled = true;
84+ previewModel.triggered(widgetId, actionId, data);
85+ }
86+
87+ onFocusChanged: if (focus) column.positionViewAtIndex(index, ListView.Contain)
88+ }
89+ }
90+ }
91+ }
92+
93+ MouseArea {
94+ id: processingMouseArea
95+ objectName: "waitingForActionMouseArea"
96+ anchors.fill: parent
97+ enabled: false
98+ }
99+}
tests/mocks/Unity/CMakeLists.txt+1
@@ -25,6 +25,7 @@ set(UnityQML_SOURCES
25 fake_scope.cpp
25 fake_scope.cpp
26 fake_scopes.cpp
26 fake_scopes.cpp
27 fake_categories.cpp
27 fake_categories.cpp
28+ scopes-ng/fake_preview_model.cpp
28 fake_unity_plugin.cpp
29 fake_unity_plugin.cpp
29)
30)
30
31
tests/mocks/Unity/fake_unity_plugin.cpp+5
@@ -25,6 +25,9 @@
25#include "fake_preview.h"
25#include "fake_preview.h"
26#include "categoryresults.h"
26#include "categoryresults.h"
27
27
28+// scopes-ng
29+#include "scopes-ng/fake_preview_model.h"
30+
28// External
31// External
29#include <glib-object.h>
32#include <glib-object.h>
30
33
@@ -44,4 +47,6 @@ void FakeUnityPlugin::registerTypes(const char *uri)
44 qmlRegisterType<Categories>(uri, 0, 1, "Categories");
47 qmlRegisterType<Categories>(uri, 0, 1, "Categories");
45 qmlRegisterUncreatableType<CategoryResults>(uri, 0, 1, "CategoryResults", "Can't create");
48 qmlRegisterUncreatableType<CategoryResults>(uri, 0, 1, "CategoryResults", "Can't create");
46 qmlRegisterType<DeeListModel>(uri, 0, 1, "DeeListModel");
49 qmlRegisterType<DeeListModel>(uri, 0, 1, "DeeListModel");
50+
51+ qmlRegisterType<scopes_ng::PreviewModel>(uri, 0, 1, "FakePreviewModel");
47}
52}
tests/mocks/Unity/scopes-ng/fake_preview_model.cppnew file+97
@@ -0,0 +1,97 @@
1+/*
2+ * Copyright (C) 2014 Canonical, Ltd.
3+ *
4+ * Authors:
5+ * Michał Sawicz <michal.sawicz@canonical.com>
6+ * Michal Hruby <michal.hruby@canonical.com>
7+ *
8+ * This program is free software; you can redistribute it and/or modify
9+ * it under the terms of the GNU General Public License as published by
10+ * the Free Software Foundation; version 3.
11+ *
12+ * This program is distributed in the hope that it will be useful,
13+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+ * GNU General Public License for more details.
16+ *
17+ * You should have received a copy of the GNU General Public License
18+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
19+ */
20+
21+// self
22+#include "fake_preview_model.h"
23+
24+// Qt
25+#include <QVariantMap>
26+
27+namespace scopes_ng
28+{
29+
30+struct PreviewData
31+{
32+ QString id;
33+ QString type;
34+ QVariantMap data;
35+
36+ PreviewData(QString const& id_, QString const& type_, QVariantMap const& data_): id(id_), type(type_), data(data_)
37+ {
38+ }
39+};
40+
41+PreviewModel::PreviewModel(QObject* parent) : QAbstractListModel(parent)
42+{
43+ m_roles[Roles::RoleWidgetId] = "widgetId";
44+ m_roles[Roles::RoleType] = "type";
45+ m_roles[Roles::RoleProperties] = "properties";
46+
47+ populateWidgets();
48+}
49+
50+void PreviewModel::populateWidgets()
51+{
52+ beginResetModel();
53+ m_previewWidgets.clear();
54+ endResetModel();
55+ beginInsertRows(QModelIndex(), 0, 4);
56+ for (int i = 0; i <= 5; ++i) {
57+ // FIXME: the API will expose nicer getters soon, use those!
58+ QVariantMap attributes;
59+ attributes["text"] = QVariant::fromValue(QString("Text"));
60+ attributes["title"] = QVariant::fromValue(QString("Title"));
61+ PreviewData* preview_data = new PreviewData(QString("widget-%1").arg(i), QString("text"), attributes);
62+ m_previewWidgets.append(QSharedPointer<PreviewData>(preview_data));
63+ }
64+ endInsertRows();
65+}
66+
67+void PreviewModel::triggered(QString widgetId, QString actionId, QVariantMap data)
68+{
69+ Q_EMIT actionTriggered(widgetId, actionId, data);
70+}
71+
72+QHash<int, QByteArray> PreviewModel::roleNames() const
73+{
74+ return m_roles;
75+}
76+
77+int PreviewModel::rowCount(const QModelIndex&) const
78+{
79+ return m_previewWidgets.size();
80+}
81+
82+QVariant PreviewModel::data(const QModelIndex& index, int role) const
83+{
84+ auto widget_data = m_previewWidgets.at(index.row());
85+ switch (role) {
86+ case RoleWidgetId:
87+ return widget_data->id;
88+ case RoleType:
89+ return widget_data->type;
90+ case RoleProperties:
91+ return widget_data->data;
92+ default:
93+ return QVariant();
94+ }
95+}
96+
97+} // namespace scopes_ng
tests/mocks/Unity/scopes-ng/fake_preview_model.hnew file+68
@@ -0,0 +1,68 @@
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+
18+#ifndef NG_FAKE_PREVIEW_H
19+#define NG_FAKE_PREVIEW_H
20+
21+#include <QAbstractListModel>
22+#include <QSharedPointer>
23+#include <QVariantMap>
24+
25+namespace scopes_ng
26+{
27+
28+class PreviewData;
29+
30+class Q_DECL_EXPORT PreviewModel : public QAbstractListModel
31+{
32+ Q_OBJECT
33+
34+ Q_ENUMS(Roles)
35+
36+public:
37+ explicit PreviewModel(QObject* parent = 0);
38+
39+ enum Roles {
40+ RoleWidgetId,
41+ RoleType,
42+ RoleProperties
43+ };
44+
45+ QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
46+ QHash<int, QByteArray> roleNames() const override;
47+ int rowCount(const QModelIndex& parent = QModelIndex()) const override;
48+
49+Q_SIGNALS:
50+ void actionTriggered(QString widgetId, QString actionId, QVariantMap data);
51+
52+public Q_SLOTS:
53+ void triggered(QString widgetId, QString actionId, QVariantMap data);
54+
55+private:
56+ QHash<int, QByteArray> m_roles;
57+ QList<QSharedPointer<PreviewData>> m_previewWidgets;
58+
59+ void populateWidgets();
60+
61+};
62+
63+} // namespace scopes_ng
64+
65+
66+Q_DECLARE_METATYPE(scopes_ng::PreviewModel*)
67+
68+#endif // NG_FAKE_PREVIW_H
tests/qmltests/CMakeLists.txt+1
@@ -54,6 +54,7 @@ add_qml_test(Dash/Apps RunningApplicationsGrid IMPORT_PATHS ${qmltest_DEFAULT_IM
54add_qml_test(Dash/Apps AppPreview IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
54add_qml_test(Dash/Apps AppPreview IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
55add_qml_test(Dash/Movie MoviePreview IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
55add_qml_test(Dash/Movie MoviePreview IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
56add_qml_test(Dash/Music MusicPreview IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
56add_qml_test(Dash/Music MusicPreview IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
57+add_qml_test(Dash/Previews Preview IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
57add_qml_test(Dash/Previews PreviewWidgetFactory IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
58add_qml_test(Dash/Previews PreviewWidgetFactory IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
58add_qml_test(Dash/Previews PreviewActions IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
59add_qml_test(Dash/Previews PreviewActions IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
59add_qml_test(Dash/Previews PreviewAudioPlayback IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
60add_qml_test(Dash/Previews PreviewAudioPlayback IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
tests/qmltests/Dash/Previews/tst_Preview.qmlnew file+75
@@ -0,0 +1,75 @@
1+/*
2+ * Copyright 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+import QtQuick 2.0
18+import QtTest 1.0
19+import Ubuntu.Components 0.1
20+import "../../../../qml/Dash/Previews"
21+import Unity.Test 0.1 as UT
22+import QtMultimedia 5.0
23+import Unity 0.1 as Unity
24+
25+Rectangle {
26+ id: root
27+ width: units.gu(60)
28+ height: units.gu(80)
29+ color: Theme.palette.selected.background
30+
31+ Item {
32+ id: shell
33+
34+ anchors.fill: parent
35+ property var applicationManager: null
36+ }
37+
38+ Unity.FakePreviewModel {
39+ id: mockPreviewModel
40+ }
41+
42+ Preview {
43+ id: preview
44+ anchors.fill: parent
45+
46+ previewModel: mockPreviewModel
47+ }
48+
49+ SignalSpy {
50+ id: triggeredSpy
51+ target: mockPreviewModel
52+ signalName: "actionTriggered"
53+ }
54+
55+ UT.UnityTestCase {
56+ name: "Preview"
57+ when: windowShown
58+
59+ function test_triggered() {
60+ var widget = findChild(preview, "widget-3");
61+
62+ compare(typeof widget, "object", "Could not find the widget object.");
63+
64+ widget.triggered(widget.widgetId, "mockAction", {"mock": "data"});
65+
66+ triggeredSpy.wait();
67+
68+ var args = triggeredSpy.signalArguments[0];
69+
70+ compare(args[0], "widget-3", "Widget id not passed correctly.");
71+ compare(args[1], "mockAction", "Action id not passed correctly.");
72+ compare(args[2]["mock"], "data", "Data not passed correctly.");
73+ }
74+ }
75+}